Skip to content

Engines

Markdown agents.txt

import { Tabs, TabItem } from ‘@astrojs/starlight/components’;

The engine field on every scrape request decides how the page is fetched and how the DSL is executed.

EngineFetchJS executionLatencyCostUse when
htmlfetch()No~100–400 ms1 creditStatic pages, SSR’d HTML, RSS, sitemaps, anything that renders without JS.
browserHeadless ChromiumYes~2–5 s5 creditsSPAs, anti-bot defenses, login flows, anything that needs JS or interaction.

Cost is per URL — see Pricing & quotas for the full table and how multi-URL requests are charged.

  1. Try html first. Cheapest (1 credit), fastest. Static / SSR pages usually have the fields in the raw HTML.
  2. Escalate to browser when html returns null or empty fields, the page is JS-rendered, or you need click / fill / wait / navigation.
  3. Use analyse (POST /analyse) when you want interpretation — outline, summary, “is X present?” — not exact CSS fields. Analyse is one LLM pass over page markdown; it does not emit CSS actions.

Prove the split on the fixture pages: /fixtures/article is static (html works); /fixtures/js-list is empty until JS runs.

Optionhtmlbrowser
options.waitForIgnoredLifecycle (load / domcontentloaded / networkidle / commit), ms delay, or CSS selector. Default goto lifecycle when waitFor is ms/selector: domcontentloaded.
options.timeoutMsHonoured — AbortController on the fetch. Default 30s, max 120s.Honoured — navigation + action timeouts. Default 30s, max 120s.
resolutionIgnoredViewport: "desktop" (1280×800), "mobile" (390×844 + mobile UA), or { width, height }.
headlessIgnoredDefault true. false renders into a real display — better fingerprint stealth, higher CPU/RAM.
blockAdsIgnoredDefault true. false stops refusing known ad/tracker hosts.
solveCaptchaIgnoredOpt-in 2captcha on detected reCAPTCHA; outcome on result.captcha.
sessionIdMatching cookies only (Cookie header). localStorage ignored.Full storageState: cookies + per-origin localStorage.

Static article. Raw HTML already has h1, p, and a.sf-cta.

{
"url": "https://scrapesilo.com/fixtures/article",
"engine": "html",
"actions": {
"title": "h1",
"body": "p",
"cta": "a.sf-cta@href"
}
}

Form needs interaction: fill the query, click submit, then extract the results.

{
"url": "https://scrapesilo.com/fixtures/form",
"engine": "browser",
"actions": {
"type": { "fn": "fill", "selector": "#sf-q", "args": "widget" },
"submit": { "fn": "click", "selector": "#sf-submit" },
"title": ".sf-result-title",
"count": ".sf-result-count"
}
}

/fixtures/js-list has no .sf-item nodes in the raw HTML — they appear after client JS. An html scrape returns empty items; browser does not.

{
"url": "https://scrapesilo.com/fixtures/js-list",
"engine": "html",
"actions": {
"items": { "selector": ".sf-item", "many": true, "output": "text" }
}
}
{
"url": "https://scrapesilo.com/fixtures/js-list",
"engine": "browser",
"actions": {
"items": { "selector": ".sf-item", "many": true, "output": "text" }
}
}

html fetches the page with undici (fetch, follow redirects) and runs the action tree over the static DOM. No JS execution.

fn actions wait, goto, click, fill, selectOption, and 2fa are rejected (warning: use browser). evaluate is allowed as sync JSDOM eval only — no async / Promise. Full fn matrix: Actions DSL.

A non-2xx response is a failure for html: that URL’s result has data: null, error set, and the captured HTTP status. Sibling URLs in the same request still return. Browser does not fail the run on a non-2xx page — it may still run actions and reports the real page status.

Full browser runtime: navigation, click / fill / select, evaluate (with async / timeout race), 2FA via otpauth. Pages run in Chromium with stealth and ad-blocking on by default.

options.waitFor controls when navigation is considered done — a lifecycle keyword (networkidle is safest for modern SPAs; domcontentloaded is fastest), a number of ms, or a CSS selector to wait for. Ignored on html. options.timeoutMs caps the per-page run at up to 120 s on both engines.

Capture a logged-in browser session once via the dashboard’s live recorder, then replay it by passing the captured id as top-level sessionId. Browser restores cookies + per-origin localStorage. Html sends only the matching cookies on the initial request (localStorage is unreachable from a plain HTTP fetch). List saved sessions with GET /sessions.

url accepts either a single URL or an array. The same actions run against every URL; the engine fans them out through a bounded pool and returns one result item per URL, so one bad URL fails on its own without sinking the batch. Each URL is charged independently (cost = per-engine credit × URL count).

EngineMax URLsRun concurrency
html5010
browser103
{
"url": [
"https://scrapesilo.com/fixtures/article",
"https://scrapesilo.com/fixtures/listing"
],
"engine": "html",
"actions": { "title": "h1" }
}

Any scrape accepts these optional top-level fields:

FieldWhat it does
useProxy: trueRoute the request through the built-in residential pool, when no BYO fields are set.
useProxy: "us"Same, but an ISO 3166-1 alpha-2 country code geo-targets the built-in pool. Ignored when BYO is set.
myProxyUrlBYO proxy as a single URL with embedded creds, e.g. http://user:pass@host:port.
myProxyConfigBYO proxy as { server, username?, password? }.

The proxy applies to both engines transparently.

{
"url": "https://scrapesilo.com/fixtures/article",
"engine": "html",
"actions": { "title": "h1" },
"useProxy": "de"
}
ScrapeSilo engines: html (1 credit, plain fetch) or browser (5 credits, Chromium).
Try html first. Escalate to browser when fields are empty, the page needs JS, or you need click/fill/wait. Use POST /analyse for interpretation, not scrape.
Rules:
- engine is only "html" | "browser". actions required. No query on /scrape.
- options.waitFor is ignored on html. timeoutMs honoured on both (default 30s, max 120s).
- resolution, headless, blockAds, solveCaptcha are browser-only.
- sessionId: html = cookies only; browser = cookies + localStorage.
- html rejects fn wait/goto/click/fill/selectOption/2fa. evaluate is sync JSDOM only.
- html non-2xx → data null + error + status. Caps: html 50 URLs, browser 10.
curl -sS -X POST https://api.scrapesilo.com/scrape \
-H "Authorization: Bearer $SCRAPESILO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://scrapesilo.com/fixtures/article",
"engine": "html",
"actions": { "title": "h1", "body": "p", "cta": "a.sf-cta@href" }
}'
curl -sS -X POST https://api.scrapesilo.com/scrape \
-H "Authorization: Bearer $SCRAPESILO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://scrapesilo.com/fixtures/form",
"engine": "browser",
"actions": {
"type": { "fn": "fill", "selector": "#sf-q", "args": "widget" },
"submit": { "fn": "click", "selector": "#sf-submit" },
"title": ".sf-result-title",
"count": ".sf-result-count"
}
}'