Use case · rendered public pages
Turn a JavaScript website into JSON
A raw HTTP response can contain an app shell while the browser-rendered page contains the product, listing, or article your integration needs. ExtractAPI can render a public page in Chromium and return bounded metadata, headings, text, structured data, links, and selected text through one authenticated REST request.
When browser rendering helps
Use it when the initial response is mostly a root element and script bundles, or when useful content appears after a client-side request. A browser is not automatically better: server-rendered HTML and an upstream JSON feed are often cheaper and simpler. Compare both paths for your target.
javascript:true enables page JavaScript, but it does not guarantee that every SPA, protected site, login flow, CAPTCHA, or third-party widget will render successfully.Input and synthetic output
The following example uses demo.example and invented values so it can be copied without contacting a real site. selector is returned as the custom array; there is no selectorText field in the API contract.
curl -X POST https://extractapi.app/v1/extract \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://demo.example/products/widget",
"javascript": true,
"waitFor": "[data-ready=\"true\"]",
"selector": "[data-price]",
"extractLinks": true
}'
{
"status": "ok",
"url": "https://demo.example/products/widget",
"data": {
"title": "Widget Pro | Demo Store",
"metaDescription": "A synthetic product page for examples.",
"h1": "Widget Pro",
"headings": [{"level":"h1","text":"Widget Pro"}],
"mainContent": "Widget Pro In stock $49.00",
"structuredData": [{"@type":"Product","name":"Widget Pro"}],
"custom": ["$49.00"],
"links": [{"text":"Specifications","href":"/products/widget/specs"}],
"pageStats": {"textLength": 31, "linkCount": 1, "imageCount": 0, "scriptCount": 4},
"canonical": "https://demo.example/products/widget",
"language": "en"
},
"responseTimeMs": 842,
"bytesReturned": 912,
"fetchedAt": "2026-09-05T00:00:00.000Z"
}
Implement it with native Node.js
The script below reads the key from the process environment, accepts a public URL, handles non-success responses, and prints only the sanitized API response. Node does not load a .env file by itself; export the variable or use your approved environment loader before starting the process.
// extract-rendered.mjs
const [target] = process.argv.slice(2);
const key = process.env.EXTRACTAPI_KEY;
if (!target || !/^https?:\/\//i.test(target)) {
console.error('Usage: EXTRACTAPI_KEY=YOUR_API_KEY node extract-rendered.mjs https://example.com');
process.exitCode = 2;
} else if (!key || /^(YOUR_API_KEY|ext_your)/i.test(key)) {
console.error('Set EXTRACTAPI_KEY to a real key before making a request.');
process.exitCode = 2;
} else {
try {
const response = await fetch('https://extractapi.app/v1/extract', {
method: 'POST',
headers: { Authorization: `Bearer ${key}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ url: target, javascript: true })
});
const body = await response.json();
if (!response.ok || body.status !== 'ok') {
console.error(JSON.stringify({ error: body.error || `HTTP ${response.status}` }));
process.exitCode = 1;
} else {
console.log(JSON.stringify(body, null, 2));
}
} catch (error) {
console.error(JSON.stringify({ error: 'Request failed', detail: error.message }));
process.exitCode = 1;
}
}
POSIX: EXTRACTAPI_KEY=YOUR_API_KEY node extract-rendered.mjs https://example.com. PowerShell: $env:EXTRACTAPI_KEY="YOUR_API_KEY"; node .\extract-rendered.mjs https://example.com. Keep the key out of shell history where practical and never commit it.
Supported workflow
- Fetch the same public URL with a lightweight client and inspect whether the required text is already in the HTML.
- If the content is client-rendered, call the API with
javascript:true; use a stablewaitForselector when the page exposes one. - Use
selectorfor a narrow field and normalize the returnedcustomtext in your own code. UsestructuredDatawhen a site publishes JSON-LD. - Persist only the fields your application needs. Track the response status and request ID when troubleshooting, not the target page’s private content.
Limitations
- The backend applies time, response-size, resource, and URL-safety bounds. A
waitFortimeout is not proof that the selector exists; inspect the returned content. - Pages that require a login, an interactive challenge, unavailable third-party APIs, or disallowed/private network access may be rejected or incomplete.
- Images, fonts, media, websockets, and other non-essential resources may be blocked to keep extraction bounded. Do not expect a pixel-identical browser session.
- Respect robots instructions, terms, privacy obligations, and rate limits for each target. ExtractAPI is a public-page data API, not a promise to bypass target controls.
FAQ
Will this work for every React or Vue site?
No. Rendering helps when the data is available to a normal public browser, but a site can still require authentication, block automated traffic, or depend on unsupported interactions. Test a representative target before designing a hard dependency.
What does the API return for JSON-LD?
Valid script[type="application/ld+json"] blocks are returned in data.structuredData, subject to response limits. Malformed blocks are skipped.
Can I turn off JavaScript?
Yes. Omit javascript or send false when the initial HTML is enough. The default authenticated extractor enables JavaScript unless explicitly disabled.