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
/akamaiand/ddare described in one machine-readable spec: download openapi.yml · browse interactively.
| Endpoint | Use when... |
|---|---|
POST /dd/solve | You've already extracted the DataDome challenge payload (dd object) and cookie from the target site yourself. |
POST /dd/mitm-solve | You 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
| Field | Type | Required |
|---|---|---|
url | absolute http(s) URL | yes |
dd | DDChallenge (see below) | yes |
ddCookie | string — the datadome cookie value | yes |
profile | ProfileSnapshot | yes |
js_profile | JsProfilePayload | yes |
proxy | string | no |
os | 'ubuntu'|'windows'|'windows10'|'windows11'|'macos' | no — otherwise derived from js_profile.os / profile.os |
script_id | string | no |
interstitialUrl | absolute URL | no |
timeout | integer ms, 1–120000 | no — default 20000 (captcha) / 8000 (interstitial) |
iframeData | { html, url, captchaLayout?, finalNavigationResponseBodySizes? } | no — skips fetching the DataDome iframe live |
spider | string | no |
DDChallenge (dd):
{
"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:
{
"body": "<solved payload string>",
"origin": "https://geo.captcha-delivery.com",
"referer": "<iframe url>",
"url": "<submit url>"
}If submit=true (default):
{ "cookie": "<new datadome cookie value>" }Error responses
400— validation failure,{ "error": "..." }. Checks include: missingurl/dd/ddCookie/profile/js_profile;ddshape (cid/hshnon-empty strings,sa finite number);url/interstitialUrlmust behttp(s);timeoutout of range; foriframeDatawithrt: "c", the iframe URL must be the canonicalhttps://geo.captcha-delivery.com/captcha/URL with matchingcid/hash/s/irquery 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
| Field | Type | Required |
|---|---|---|
original_url | absolute http(s) URL | yes |
profile_id | string, chrome-<ver>-<os> | yes |
challenge_body | non-empty string | yes |
challenge_headers | [string,string][] — must include a Set-Cookie: datadome=... | yes |
js_profile | JsProfilePayload | yes |
interstitial_url | absolute URL | no |
http_header_templates | HeaderTemplates | no |
device_memory | number | no |
script_id | string | no |
proxy_url / upstream_proxy | string | no |
sec_ch_ua, sec_ch_ua_arch, sec_ch_ua_full_version_list, sec_ch_ua_model | string | no |
timezone, timezone_offset_minutes | no | |
user_agent | string | no |
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
{ "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.