Scrape JavaScript websites
Send a URL that needs JavaScript. Get the page back as clean Markdown or JSON.
{ "url": "https://shop.example/product/1", "js_render": true, "cache": true, "response_format": "markdown"}- X-Target-Status
- 200
- X-Engine
- obscura
- X-Proxy-Source
- direct
- Cache-State
- hit
- X-Credits-Charged
- 0
Start with a plain request and move up to a real browser only if the site says no. You are charged for the engine that worked, and a blocked or refused request costs nothing.
Render JavaScript in a real browser, or run it headful with a real display for sites that check for headless. A pinned engine never escalates, so headful turns auto mode off.
Plain requests carry a real browser’s TLS and HTTP/2 fingerprint, which gets past checks that never run JavaScript.
Use a direct connection or your own proxy with no proxy surcharge. Managed proxies and built-in country targeting are coming soon, outside the current beta.
Keep cookies and storage between requests, so a login carries over. Session requests are never served from the cache.
Click, type, select, scroll and run JavaScript before the page is read. The same steps run on every browser engine.
Skip images, fonts and media while rendering. Pages load faster and you move fewer bytes.
Record every request the page itself made while it loaded: the API calls behind the page, not just its HTML.
On by default for up to 48 hours. A repeat of the same request is served from the cache at no charge.
A rendered page, in the format you need
See how page content becomes Markdown, JSON or HTML. These examples show the output, not a live request.
# Wireless Mouse — Model X**$49.00** · In stock · 4.6 (1,284 reviews)Low-latency 2.4 GHz receiver, 70-day battery lifeand silent switches.| Spec | Value || --------- | ------------ || Connection| 2.4 GHz, BT5 || Battery | 70 days |Menus, footers, ads and images removed. About a tenth of the tokens of raw HTML. Token counts are from an example page.
The full reply: status, final URL, engine, warnings, and your data. Token counts are from an example page.
Three ways to get fields: free page info, CSS rules, or a JSON Schema with selectors. Token counts are from an example page.
A list of steps to run on the page. The same steps work on every engine.
How it works
- Send the page URL to
POST /v1/scrapewithjs_render: true. - Wait for the content. Set
wait_forto a CSS selector, such as.price. - Get the rendered page in the format you choose. The examples below return Markdown.
curl -sS -D - https://api.spicrawl.com/v1/scrape \
-H "Authorization: Bearer $SPICRAWL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/products/42", "js_render": true, "wait_for": ".price", "response_format": "markdown"}'import os, requests
r = requests.post(
"https://api.spicrawl.com/v1/scrape",
headers={"Authorization": f"Bearer {os.environ['SPICRAWL_API_KEY']}"},
json={"url": "https://example.com/products/42", "js_render": True, "wait_for": ".price", "response_format": "markdown"},
timeout=180,
)
print("site status:", r.headers.get("X-Target-Status"))
print(r.text)const r = await fetch("https://api.spicrawl.com/v1/scrape", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.SPICRAWL_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ url: "https://example.com/products/42", js_render: true, wait_for: ".price", response_format: "markdown" }),
});
console.log("site status:", r.headers.get("X-Target-Status"));
console.log(await r.text());spicrawl scrape https://example.com/products/42 --render --wait-for .price --format markdown --metaKeep your key in SPICRAWL_API_KEY. Never put it in browser code or a file you commit.
When to render JavaScript
A plain request downloads HTML without running scripts. If the result is an empty shell or a “Loading…” message, the page may need JavaScript. Set js_render: true to run it in a browser before reading it.
Use a plain request for content already in the HTML. Rendering is also needed for browser actions, resource blocking and network capture.
Wait for the right content
| Option | What it does |
|---|---|
wait_for | Wait for a CSS selector to appear before capture. |
wait_for_timeout | Set the wait limit from 0 to 120,000 ms. Requires wait_for; 0 uses the engine default. |
wait | Add a fixed delay from 0 to 30,000 ms after load. Prefer a selector when you can. |
block_resources | Choose which assets to skip. Images and fonts are blocked by default, with exceptions for actions and captures. |
response_format | Choose Markdown, JSON or HTML for the page content. |
An explicit resource list replaces the default. Use ["none"] to block nothing. Do not block scripts when the page needs them to build its content.
Check the result
HTTP/2 200
content-type: text/markdown; charset=utf-8
x-target-status: 200
x-engine: obscura
x-credits-charged: 3X-Engine tells you which engine ran. X-Target-Status is the site's status, while X-Credits-Charged shows the charge.
If wait_for never matches, the page may come back as it stood with X-Warning: RENDER_DEGRADED. Check the content and warning before using it.
Choose an engine and check the cost
- Free during beta. Credits show the cost of each request.
- Browser rendering:
js_render: truenormally uses Obscura, at 3 credits per successful request. - Chromium: costs 8 credits. If Obscura is not deployed, an unpinned render may use Chromium and return
X-Warning: ENGINE_SUBSTITUTED. - Pin an engine with
engine: "obscura"to avoid substitution. Your plan must allow it; a pinned engine never escalates. - Failures cost 0. Waiting and resource blocking add no extra charge. Set
max_costto cap a request.
Good to know
- Choose rendering or auto mode.
mode: "auto"cannot be combined withjs_renderorengine. It starts with fetch and may move to Obscura; it never reaches Chromium. - Browser flags need a browser. Sending
wait_for, actions or resource blocking with the fetch engine returns an error. - No crawling. Send the URLs you want; Spicrawl does not find pages or follow links.
- Coming soon: managed proxies, stealth mode, a remote browser and extraction from a plain-language prompt.
- Your responsibility: only fetch pages you have the right to use. Read our terms.
Frequently asked questions
How do I scrape a JavaScript website?
Send the page URL to POST https://api.spicrawl.com/v1/scrape with js_render set to true. The browser runs the scripts before Spicrawl reads the page. Choose response_format for Markdown, JSON or HTML.
How do I wait for content to load?
Set wait_for to a CSS selector, such as .price. Use wait_for_timeout to set a timeout up to 120000 milliseconds. If the selector never matches, the page may come back as it stood with X-Warning: RENDER_DEGRADED. Check the warning before using the result.
How much does JavaScript rendering cost?
Spicrawl is free during beta. Successful Obscura renders use 3 credits; Chromium uses 8. If js_render is true without a pinned engine, Chromium may serve the request when Obscura is not deployed. Failed requests use 0 credits. Read X-Engine and X-Credits-Charged to check what ran.
Can I use auto mode with JavaScript rendering?
No. mode: auto cannot be combined with js_render or engine. Auto mode starts with a plain request and moves to Obscura when the result is unusable. For pages you know need JavaScript, use js_render: true instead.
Can it crawl a JavaScript website?
No. Spicrawl does not find URLs or follow links. Send the page URLs you want to read. Only fetch pages you have the right to use.