Skip to content

Service node settings

A service node in a workflow calls one provider with one set of options. The properties panel surfaces 13 settings grouped into four disclosure sections: Basic, Output formats, Identity, and Advanced. Vendor-specific fields render below the shared sections.

This page is the reference for every option. If a setting isn’t supported by your selected provider, the workflow editor hides it. The capability matrix in Providers shows which providers expose which options.

All settings flow through node.config.scrapeOptions and are spread into the provider adapter’s ScrapeRequest. The TypeScript shape is:

interface ScrapeRequest {
url: string;
// --- Basic --------------------------------------------------------------
country?: string; // ISO-2 lowercase: 'us', 'gb', 'de'
renderJs?: boolean;
waitForSelector?: string; // CSS selector
waitForSelectorTimeout?: number; // milliseconds
// --- Output formats -----------------------------------------------------
parse?: boolean;
markdown?: boolean;
screenshot?: boolean;
// --- Identity -----------------------------------------------------------
customHeaders?: Record<string, string>;
customCookies?: Record<string, string>;
sessionId?: string;
device?: 'desktop' | 'mobile' | 'tablet';
// --- HTTP control -------------------------------------------------------
httpMethod?: 'GET' | 'POST';
httpBody?: string;
// --- Vendor-specific (passthrough) --------------------------------------
[key: string]: unknown;
}

The adapter is responsible for converting these typed fields to vendor-specific request bodies. Every adapter applies the same field semantics; only the wire format differs.


These four settings are visible by default in the Scrape Options panel for every supported provider.

Geo-target the proxy. Lowercase ISO-2 country code. The workflow editor surfaces the most common 14 (US, UK, DE, FR, JP, IN, BR, AU, CA, ES, IT, MX, KR, NL); for any other code, use Advanced (JSON): {"country": "se"}.

{ "country": "us" }

Adapters convert to vendor-native format:

  • Bright Data: passed as-is (lowercase).
  • Oxylabs / Decodo: converted to full country name ("us""United States").
  • Nimble Way / Zyte: uppercased ("us""US").

Toggle. Enable headless browser rendering. Required for waitForSelector, screenshots, and most modern dynamic sites.

{ "renderJs": true }

Bright Data: always-on. Web Unlocker can’t disable JS — the toggle is shown disabled-checked.

CSS selector to wait for in the rendered DOM before returning the body. Requires renderJs: true (except on Bright Data, where rendering is implicit).

{ "waitForSelector": ".product-title", "waitForSelectorTimeout": 15000 }

Timeout for waitForSelector in milliseconds. Default 10000 (10s). Adapters convert to vendor-native units (Zyte uses seconds; Oxylabs/Decodo/Nimble use milliseconds).


Three toggles that change the response body type. Only one effective format applies per request — if multiple are set, the adapter picks per its own precedence rules. The response includes contentType so downstream validators know what to expect.

Toggle. Request the vendor’s parsed JSON output instead of raw HTML.

{ "parse": true }
  • Oxylabs: parse: true returns Oxylabs’s structured JSON (e.g., Amazon product fields). Body is JSON.stringify(parsed_data), contentType: application/json.
  • Decodo: same shape — parse: trueparsed_data with contentType: application/json.
  • Zyte: auto-extraction (product / article / jobPosting) is TODO 3; the flags work via Advanced (JSON) but the contentType pipeline isn’t wired yet.
  • Bright Data / Nimble Way: not supported.

Toggle. Returns a base64-encoded PNG of the rendered page.

{ "screenshot": true }
  • Body is a base64 PNG string. contentType: image/png.
  • Implies rendering on every supported provider.
  • Zyte: screenshot is its own browser-mode trigger (doesn’t require renderJs). Adds a per-request cost.
  • Oxylabs / Decodo: screenshot wins over markdown and renderJs if multiple are set.
  • Bright Data: screenshot wins over markdown if both are set.

Toggle. Returns markdown-converted body text instead of HTML.

{ "markdown": true }
  • Body is plain markdown. contentType: text/markdown.
  • Decodo: auto-enables headless rendering when set.
  • Oxylabs / Zyte: not supported.

Headers, cookies, sessions, and device emulation — anything that affects how the proxy request looks to the target site.

Key/value editor in the UI. Stored as a flat Record<string, string>.

{
"customHeaders": {
"User-Agent": "MyScraper/1.0",
"Accept-Language": "en-US,en;q=0.9"
}
}
  • Bright Data: merged into request body headers. Requires “Custom Headers & Cookies” enabled on the zone.
  • Oxylabs: passed via context: [{key: "headers", value: {...}}].
  • Nimble Way: body.headers (object).
  • Zyte: branched by mode — HTTP mode uses customHttpRequestHeaders (array, full passthrough); browser mode uses requestHeaders (object, only Referer honored).
  • Decodo: body.headers object.

Key/value editor in the UI. Stored as a flat Record<string, string> of cookie name → value.

{
"customCookies": {
"session_token": "abc123",
"preferred_lang": "en"
}
}

Each cookie’s domain defaults to the request URL’s hostname when the adapter assembles the wire payload (eng-review A2). Override per-cookie via Advanced (JSON) if you need a different domain (e.g., .example.com for subdomain coverage).

  • Bright Data: not supported (Web Unlocker has no first-class cookie passthrough).
  • Oxylabs / Decodo: flat record passed via vendor-native shape.
  • Nimble Way: array of {key, value, domain} with auto-default domain.
  • Zyte: array of {name, value, domain} with auto-default domain.

Free-form text. Sticky-session ID for providers that support session continuity (same IP across multiple requests).

{ "sessionId": "user-checkout-flow-1" }
  • Oxylabs: passed via context: [{key: "session_id", value: ...}].
  • Zyte: passed as session.id. Zyte requires v4 UUIDs — the adapter SHA-1-hashes any free-form string to a deterministic v4 UUID, so the same sessionId always produces the same Zyte session.
  • Decodo: session_id.
  • Bright Data / Nimble Way: not supported.

Select. desktop / mobile / tablet. Adapters map to vendor-specific user-agent / driver / device-type fields.

{ "device": "mobile" }
  • Oxylabs: user_agent_type (tablet → mobile).
  • Nimble Way: drives driver selection — mobile / tabletvx10-pro with rendering enabled. desktop alone is a no-op (combine with renderJs or waitForSelector).
  • Zyte: HTTP mode only (browser mode silently drops). Tablet → mobile.
  • Decodo: device_type passed as-is.
  • Bright Data: not supported.

A free-form JSON textarea per provider. Power-user passthrough — anything you put in is shallow-merged into the final wire request last, so it can override anything the typed surface set.

{
"advancedOptions": "{\"viewport\": {\"width\": 1280}, \"sessionContext\": [{\"name\": \"loggedIn\"}]}"
}

The textarea accepts a JSON object. Validation happens on blur and on save:

  • Invalid JSON → inline error, save blocked.
  • Non-object root (array, string, number) → rejected.
  • Keys __proto__, constructor, prototype at the root → rejected (prototype-pollution defense).

Use cases by provider:

  • Bright Data: any field the typed surface doesn’t expose (data_format overrides, custom dataset filters).
  • Oxylabs: parsing_instructions (custom parser), geo_location overrides, extra context entries.
  • Nimble Way: parsing (CSS-selector schema), network_capture, locale, sub-country state/city, custom viewport.
  • Zyte: viewport, actions (full sequences beyond waitForSelector), sessionContext, auto-extract flags (product: true, article: true, jobPosting: true — TODO 3).
  • Decodo: pages, start_page, vendor flags not exposed in typed UI.

Override semantics. If you set country: "us" in the typed UI and {"country": "uk"} in Advanced (JSON), the JSON wins. Useful for testing; risky for production. Workflow validation does not flag conflicts.


Below the shared groups, each provider renders its own fields. These don’t have shared capability flags because they don’t generalize across vendors:

ProviderFieldNotes
Bright DataZone (select)Required. Web Unlocker zone from your account. See Bright Data > Required configuration.
Bright DataResponse Format (json / raw)Optional. Default json.
OxylabsSource (select, 80+)Optional override of auto-detection. Empty = auto.
Nimble WayDriver (select)Optional override of inferred stealth profile.
ZyteIP Type (datacenter / residential)Optional. Residential requires KYC + per-request surcharge.
DecodoTarget (select, 40+)Optional override of auto-detection.
DecodoProxy Pool (standard / premium)Optional.
DecodoPage From / Page CountOnly meaningful for paginated targets (google_search, amazon_search).

When submitting a job via API, pass scrapeOptions in the request body. The fields match the ScrapeRequest shape above.

Terminal window
curl -X POST https://dashboard.justcrawl.io/api/v1/jobs \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://www.amazon.com/dp/B08Y72CH1F",
"scrapeOptions": {
"country": "us",
"parse": true,
"device": "desktop",
"customHeaders": {
"Accept-Language": "en-US"
}
}
}'

The workflow router resolves which provider to use (based on domain routing + smart strategy), and the chosen provider’s adapter consumes the shared fields above plus any vendor-specific extras you pass through.

For the full API request/response schemas, see the API ReferenceScrapeOptions is documented under the POST /api/v1/jobs endpoint.


Service-node responses include a contentType discriminator that drives downstream validation:

contentTypeMeaningValidation behavior
text/html (default)Rendered HTML bodyvalidateHtml runs (size, error patterns, selectors).
application/jsonParsed structured data (parse mode)HTML validator skipped.
image/pngBase64-encoded screenshotHTML validator skipped.
text/markdownMarkdown-converted textHTML validator skipped.

This means turning on Parse, Screenshot, or Markdown automatically bypasses any HTML output-validation rules you’ve configured on the node — the validator knows the body isn’t HTML.