Stealth Mode
Full-browser rendering for JavaScript-heavy pages
Stealth mode will no longer be available from 1 November 2026. Search and Extract are unchanged.
What Stealth Mode Solves
Some pages need a real browser to render fully. Common cases:
- JavaScript rendering requirements — pages that return blank HTML until scripts run
- Heavy client-side frameworks — content that's assembled dynamically after the initial page load
- Complex page behavior — pages that need real browser events to finish loading
Standard extraction (stealth: false) sends a direct HTTP request. This works well for the vast majority of public websites and is both fast and cost-efficient.
Stealth mode renders the page in a full browser and executes its JavaScript before returning the content. Use it only when standard extraction returns incomplete content or fails.
When to Use Stealth vs Normal
| Situation | Recommendation |
|---|---|
| Public articles, blogs, documentation | Normal extraction (1 credit/URL) |
| E-commerce product pages | Try normal first; use stealth if the result is incomplete |
| Sites requiring JavaScript to render content | Stealth mode |
| Sites with heavy client-side rendering | Stealth mode |
| High-volume batch extraction | Normal mode; fall back to stealth on failure |
Example
curl -X POST https://api.serpex.dev/api/crawl \
-H "Authorization: Bearer sk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"urls": ["https://example-protected-site.com/product/123"],
"stealth": true,
"format": "html"
}'import { SerpexClient } from "serpex";
const client = new SerpexClient("sk_your_api_key");
const result = await client.extract({
urls: ["https://example-protected-site.com/product/123"],
stealth: true,
format: "html",
});
if (result.results[0].success) {
// Parse structured data from HTML
console.log(result.results[0].html);
} else {
console.error(result.results[0].error);
}from serpex import SerpexClient
client = SerpexClient("sk_your_api_key")
result = client.extract({
"urls": ["https://example-protected-site.com/product/123"],
"stealth": True,
"format": "html",
})
if result.results[0].success:
# Parse structured data from HTML
print(result.results[0].html)
else:
print(result.results[0].error)Response
The response shape is the same as normal extraction. metadata.stealth and results[].stealth (both true) show stealth mode was active.
{
"success": true,
"results": [
{
"url": "https://example-protected-site.com/product/123",
"success": true,
"html": "<!DOCTYPE html><html>...",
"stealth": true,
"status_code": 200
}
],
"metadata": {
"total_urls": 1,
"processed_urls": 1,
"successful_crawls": 1,
"failed_crawls": 0,
"credits_used": 5,
"stealth": true,
"response_time": 11000,
"timestamp": "2025-06-21T10:30:00.000Z"
}
}Performance
Stealth requests are significantly slower than normal extraction — each one loads the page in a full browser and waits for its JavaScript to finish executing.
| Mode | Typical time per URL |
|---|---|
| Normal extraction | ~1–5s |
| Stealth | ~7–15s (up to ~25s for JavaScript-heavy sites) |
Set your client timeout to at least 60 seconds for stealth requests. Batch requests (up to 10 URLs) are processed concurrently, so total time is bounded by the slowest URL — not the sum.
Cost
Stealth mode costs 5 credits per URL, compared to 1 credit per URL for normal extraction. Only use it when standard extraction is insufficient.
- Normal extraction: 1 credit/URL
- Stealth mode: 5 credits/URL
- Repeats: 0 credits when your organization requests the same URL with the same
formatin stealth mode again within 5 minutes of the charged request
Failed stealth requests are not charged.