How DataDome actually detects bots
How DataDome scores requests from device fingerprint, TLS and behavioral tags, why headless browsers get caught, and what a passing request looks like.

Most people meet DataDome the same way: a scraper that worked yesterday starts returning a 403, or a slider captcha appears where the page used to be. The instinct is to add a proxy or swap the user agent. It rarely helps, because DataDome is not looking at any single signal. It is scoring a whole picture of the request, and the fix is to send a picture that looks real.
Here is what it actually looks at.
The device fingerprint
DataDome's JavaScript runs in the page and collects a fingerprint of the client: screen and window dimensions, timezone, language, installed fonts, canvas and WebGL hashes, the list of supported codecs, and dozens of smaller signals. On its own this fingerprint is not a verdict. It is an identity that DataDome tracks across requests, so an inconsistent or impossible combination (a "Chrome on Windows" user agent paired with a Linux WebGL renderer) stands out immediately.
TLS and header order
Before any JavaScript runs, DataDome already has two strong signals from the connection itself:
- The TLS fingerprint (JA3/JA4). The exact cipher suites and extensions your HTTP client offers rarely match a real browser. A default
requestsoraxioshandshake is trivially distinguishable from Chrome's. - The header order and casing. Browsers send headers in a specific, stable order. Most HTTP libraries do not, and DataDome reads that order as a tell before it reads any header value.
This is why swapping the User-Agent string alone changes nothing. The string says Chrome; the handshake says Python.
The behavioral tags
Once the page loads, DataDome streams a payload of behavioral tags back to its collection endpoint: mouse movement, scroll timing, key cadence, focus and blur events, and the timing between them. A real session produces a messy, human-shaped stream. A headless browser produces either nothing or something too clean and too fast.
The response to that payload is what sets the datadome cookie. Get the payload right and the cookie comes back in a trusted state. Get it wrong, or skip it, and you are handed the interstitial or the slider.
Why headless browsers still get caught
Running Puppeteer or Playwright generates real tags and a real TLS handshake, so it clears more than a raw HTTP client. But it is slow (seconds per session, hundreds of MB of RAM per worker) and it leaves its own fingerprints: navigator.webdriver, headless-specific rendering quirks, and automation-framework timing patterns that stealth plugins patch one release behind. You end up maintaining a browser farm and a plugin treadmill to fight a detector that updates faster than you can.
What a passing request looks like
A request DataDome trusts carries three things that agree with each other:
- A valid
datadomecookie in its cleared state. - The TLS fingerprint and header set the cookie was issued against.
- A downstream request from an IP that fits the target's policy (bring your own proxy).
The hard part is producing the first two without a browser. That is exactly what we do: generate the tags payload, solve the device check and the slider server-side, and hand back the datadome cookie plus the header set it was signed against. You attach them to your own request and go straight to the data. No headless Chrome, no stealth plugins, no cat-and-mouse.
If you want the mechanics and a working example, see the DataDome bypass page. If you are getting blocked by a different vendor, the full list of walls covers Akamai, Cloudflare, PerimeterX, Imperva and the rest.
Skip the reverse-engineering.
Takion returns fresh cookies, headers, and tokens for every major antibot wall. One POST, no browser, first call within the hour.