parsa
Get started

DataDome solver API

Send the challenge page DataDome served you, get back the payload that earns the datadome cookie. The interstitial device check, the slider captcha and the tags.js beacons, with no browser and nothing to pay when a solve fails.

How DataDome blocks a visit, and where Parsa fits
Challenges
Interstitial, slider, tags
Answer time
~40 ms; 0.2–0.3 s for a new build
Browsers
Chrome on macOS
Price
From €0.50 / 1,000
Billed
Only answers that come back 200

Measured in November 2026 on our own solvers; how, under benchmarks.

What is DataDome?

DataDome is a bot protection service that sits in front of a site, at its CDN or web server, and scores every request in real time. A visitor it trusts carries a datadome cookie; a visitor it doesn't gets a 403 page instead of the content. That page holds a small object, var dd = {…}, and its rt field tells you which challenge you are facing: i for the interstitial device check, c for the slider captcha.

Both challenges run in an iframe from geo.captcha-delivery.com. The interstitial runs DataDome's device check: a bytecode virtual machine and a WebAssembly module that probe the browser and bind what they find to this challenge. The slider asks for a puzzle piece to be dragged into its gap and watches how the pointer moves. On pages that are not challenged, DataDome's tags.js script reports on the visit in the background and refreshes the cookie.

A plain HTTP client can't run any of this, so its first 403 is where it stops. Parsa computes what the browser would have sent. You fetch the challenge as a browser would, send it to us with your user agent, IP and language, and post what we return. DataDome answers with a datadome cookie and your client retries the page.

How DataDome works, in depth →

Interstitial (device check)

POST /datadome/interstitial · €1.00 / 1,000

The interstitial is the challenge you meet most: a 403 whose page sets var dd with rt:'i' and loads DataDome's i.js. From the dd object you build the device link on geo.captcha-delivery.com, fetch it as a browser would, and send its HTML to us.

Parsa runs the device check's virtual machine and attestation for the device your user agent describes, with a time zone and language consistent with your IP, and returns a form body to post to geo.captcha-delivery.com/interstitial/. DataDome answers view:redirect with a datadome cookie; retry the page with it.

You send
deviceLink
The geo.captcha-delivery.com link built from dd
html
The body of your GET to that link
script
Optional: the bundle, when the page links it
userAgent
A Chrome on macOS user agent
ip
Your proxy's exit IP
acceptLanguage
The Accept-Language you send
You get back
payload
A form body to post
url
geo.captcha-delivery.com/interstitial/
headers
Six client hints to send from now on

Slider captcha

POST /datadome/slider · €2.00 / 1,000

When DataDome trusts a visit less, the 403 page sets rt:'c' and the device link points at a /captcha/ page with a puzzle: a background image with a gap and a piece to drag into it. Fetch the device link and the puzzle image, and send both to us.

Parsa finds the gap from the image, writes a human pointer path to it with its own timing, and runs the same device check as the interstitial. You get back the /captcha/check URL to request and waitMs, how long the slide takes; wait that long, request the URL, and the answer carries the datadome cookie.

You send
deviceLink
The /captcha/ link built from dd
html
The body of your GET to that link
puzzle
The puzzle .jpg, base64
userAgent, ip, acceptLanguage
As for the interstitial
You get back
payload
The /captcha/check?… URL to GET
waitMs
How long to wait before you send it
headers
The client hints to send with it

Tags (tags.js beacons)

POST /datadome/tags · €0.50 / 1,000

Pages that aren't challenged still load DataDome's tags.js, which sets window.ddjskey and reports on the visit to api-js.datadome.co/js/ or the site's own /js/ path. A browser sends a ch beacon when the page loads and an le beacon about ten seconds after the first mouse move; each answer refreshes the datadome cookie.

Sending these beacons keeps a session's cookie fresh and its score high, which is how you avoid meeting the interstitial in the first place. Send the page's ddjskey and referer, and for le the cookie the ch beacon set.

You send
ddk
The page's 30-character ddjskey
referer
The page
type
ch (on load, the default) or le
cid
For le: the datadome cookie from ch
userAgent, ip, acceptLanguage
As above
You get back
payload
A form body to post
url
api-js.datadome.co/js/ or the site's /js/
headers
The client hints to send with it

The request

Your client reads rt from the 403's var dd object, builds the device link, fetches it (and the puzzle image for a slider) and sends the HTML to us. It posts the payload to the URL we return, with the client hints from headers, and retries the page with the datadome cookie DataDome sets.

Keep these the same for the whole session

  • One exit IP, sticky, and the same one you send us as ip
  • A Chrome TLS and HTTP/2 fingerprint and Chrome's header order
  • The user agent and Accept-Language the payload describes
  • One cookie jar, from the first page load to the protected request
curl https://api.parsalabs.io/datadome/interstitial \
  -H "Authorization: Bearer parsa_…" \
  -H "Content-Type: application/json" \
  -d '{
    "userAgent":      "Mozilla/5.0 (Macintosh; …)",
    "deviceLink":     "https://geo.captcha-delivery.com/…",
    "html":           "<!DOCTYPE html>…",
    "ip":             "203.0.113.7",
    "acceptLanguage": "en-US,en;q=0.9"
  }'

# 200 OK · charged €0.001
{
  "payload": "…",
  "url":     "https://geo.captcha-delivery.com/interstitial/",
  "headers": { "sec-ch-ua-platform": "\"macOS\"", … }
}
import requests
from curl_cffi import requests as browser

s = browser.Session(impersonate="chrome", proxy=PROXY)
html = s.get(device_link).text

ans = requests.post(
    "https://api.parsalabs.io/datadome/interstitial",
    headers={"Authorization": "Bearer parsa_…"},
    json={"userAgent": UA, "deviceLink": device_link,
          "html": html, "ip": exit_ip,
          "acceptLanguage": "en-US,en;q=0.9"},
).json()

r = s.post(ans["url"], data=ans["payload"], headers={
    **ans["headers"],
    "Content-Type": "application/x-www-form-urlencoded",
})
# r.json()["cookie"] holds datadome=…; retry the page
const res = await fetch("https://api.parsalabs.io/datadome/interstitial", {
  method: "POST",
  headers: {
    "Authorization": "Bearer parsa_…",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    userAgent, deviceLink, html,
    ip: exitIp,
    acceptLanguage: "en-US,en;q=0.9",
  }),
});
const { payload, url, headers } = await res.json();
// POST payload to url, form-encoded, with these
// headers, from your Chrome-fingerprinted client.
// The reply sets the datadome cookie.

Benchmarks

Measured on our solver. The time below is what we spend computing an answer, which your client waits for on top of the round trip to api.parsalabs.io. A browser has to run the same device check in the page, after it has started and loaded the challenge.

MeasureParsaHeadless Chromium
Interstitial answer (known build)About 40 msThe device check runs in the page
First answer for a new build0.2 to 0.3 sThe page and bundle load each session
Throughput, one machineAbout 255 interstitials/s, 245 to 300 sliders/s, 500 tags/sOne challenge at a time per tab
Memory per solver workerAbout 8 MBA browser per session (below)
Live checks so far34 of 37 interstitial and slider runs cleared–
Memory per sessionNone on your side: a JSON request277 MB for the first, about 102 MB for each one after
Ten sessions at onceTen HTTPS requests1,198 MB of Chromium
Start-up, before any networkNoneAbout 100 ms to launch and load an empty page

DataDome pricing, from

€0.50per 1,000 solves

Prepaid from €5, no plan and no monthly fee. Only an answer that comes back 200 is billed: an error, a timeout or a build we can't read costs nothing.

Interstitial (device check)
€1.00 / 1,000
Slider captcha
€2.00 / 1,000
Tags (tags.js beacons)
€0.50 / 1,000

DataDome questions

How do I tell which DataDome challenge I got?

Look at the 403 page's var dd object. rt:'i' is the interstitial device check, rt:'c' the slider captcha. A page that loads tags.js without a 403 isn't challenging you; its beacons keep the cookie fresh.

How long does a datadome cookie last?

DataDome sets it with a long Max-Age, a year in the answers we've seen, but it re-scores the visitor on every request. A session that changes IP or fingerprint, or behaves unlike a browser, is challenged again whatever the cookie says.

Which user agents are supported?

Chrome on macOS, from our built-in device list. Windows agents are refused with a 400 for now: their answers didn't clear in our live checks, so we would rather say no than bill you for a cookie that won't work.

Why must the ip and acceptLanguage match my real requests?

The device check reports a time zone and languages, and DataDome compares them with the IP and headers it sees. We derive them from the ip and acceptLanguage you send, so they have to be the ones your client really uses.

What are the headers in every answer?

Six Chrome client hints (sec-ch-ua-platform, sec-ch-ua-full-version-list and the rest) that match the device in the payload. Send them on the post to DataDome and on every request after it.

Do I need the slider at all?

Only when DataDome serves it. Keep your sessions clean (sticky residential IPs, a browser TLS fingerprint, tags beacons) and you will mostly meet the interstitial or nothing.

Am I charged for a solve that fails?

No. An interstitial costs €0.001 and a slider €0.002, and only when the API answers 200. A 500 means the solve failed: fetch the challenge again and retry, free.

GuideHow DataDome worksRead the guide →

Other solvers