Skip to content

DataDome API Reference

Solves DataDome captcha (rt: "c") and interstitial (rt: "i") challenges. Both endpoints are mounted under /dd (http://host:3000/dd/...).

Unlike Akamai, DataDome solving is single-shot HTTP — there's no WebSocket session. Each request fully resolves one challenge and returns.

Both /akamai and /dd are described in one machine-readable spec: download openapi.yml · browse interactively.

EndpointUse when...
POST /dd/solveYou've already extracted the DataDome challenge payload (dd object) and cookie from the target site yourself.
POST /dd/mitm-solveYou run a MITM proxy and hand over the raw captured 403/challenge response — the solver parses the challenge and cookie itself.

All error responses include an error field. Validation failures return 400.

POST /dd/solve

Request body

FieldTypeRequired
urlabsolute http(s) URLyes
ddDDChallenge (see below)yes
ddCookiestring — the datadome cookie valueyes
profileProfileSnapshotyes
js_profileJsProfilePayloadyes
proxystringno
os'ubuntu'|'windows'|'windows10'|'windows11'|'macos'no — otherwise derived from js_profile.os / profile.os
script_idstringno
interstitialUrlabsolute URLno
timeoutinteger ms, 1120000no — default 20000 (captcha) / 8000 (interstitial)
iframeData{ html, url, captchaLayout?, finalNavigationResponseBodySizes? }no — skips fetching the DataDome iframe live
spiderstringno

DDChallenge (dd):

json
{
  "cid": "string",
  "hsh": "string",
  "rt": "c",
  "s": 1,
  "ir": 12345,
  "t": "fe",
  "b": 1,
  "e": "..."
}

rt must be "c" (captcha) or "i" (interstitial) — anything else returns 400 "not implemented". t: "bv" returns 422 "IP is banned".

Query param: ?submit=false returns the built payload without POSTing it to DataDome (default is true, i.e. submit).

Success response 200

If submit=false:

json
{
  "body": "<solved payload string>",
  "origin": "https://geo.captcha-delivery.com",
  "referer": "<iframe url>",
  "url": "<submit url>"
}

If submit=true (default):

json
{ "cookie": "<new datadome cookie value>" }

Error responses

  • 400 — validation failure, { "error": "..." }. Checks include: missing url / dd / ddCookie / profile / js_profile; dd shape (cid/hsh non-empty strings, s a finite number); url / interstitialUrl must be http(s); timeout out of range; for iframeData with rt: "c", the iframe URL must be the canonical https://geo.captcha-delivery.com/captcha/ URL with matching cid / hash / s / ir query params.
  • 422{ "error": "DD submit failed with status: <n>" } or { "error": "No cookie in submit response" }.
  • 500{ "error": "DD solve error: <message>" }, including a timeout-based rejection: "Failed to solve in <n>ms".

POST /dd/mitm-solve

For MITM-proxy architectures — hand over the captured challenge response directly. The solver parses the DataDome challenge and cookie out of it, fetches whatever DataDome assets it needs, solves, submits, and returns a merged cookie header (including a favicon-request cookie merge step for interstitials).

Request body

FieldTypeRequired
original_urlabsolute http(s) URLyes
profile_idstring, chrome-<ver>-<os>yes
challenge_bodynon-empty stringyes
challenge_headers[string,string][] — must include a Set-Cookie: datadome=...yes
js_profileJsProfilePayloadyes
interstitial_urlabsolute URLno
http_header_templatesHeaderTemplatesno
device_memorynumberno
script_idstringno
proxy_url / upstream_proxystringno
sec_ch_ua, sec_ch_ua_arch, sec_ch_ua_full_version_list, sec_ch_ua_modelstringno
timezone, timezone_offset_minutesno
user_agentstringno

The challenge itself is not passed explicitly — it's parsed from challenge_body, and the datadome cookie is extracted from challenge_headers. Both must parse successfully or the request 400s.

js_profile must satisfy DataDome's critical fingerprint checks: hardware.webgl.vendor and hardware.webgl.renderer must be non-empty, and screen.outerHeight - screen.innerHeight must be greater than 1 (proves real browser chrome, not a headless window).

Success response 200

json
{ "success": true, "cookies": "datadome=...; other=...; ..." }

A full merged Cookie: header string — original challenge-response cookies plus solved-submission cookies, plus (for interstitials) a favicon-request cookie merge.

Error responses

Always shaped { "success": false, "cookies": "", "error": "<message>" }:

  • 400 — any validation or challenge-parse failure above.
  • 422 — submit failed ("Submit failed with status <n>") or "No cookie in submit response".
  • 500 — unexpected solve error.

Note: unlike /dd/solve, the sandbox timeout here is fixed (45s) and not configurable per request.