Most request-based developers already know that header order is extremely important.
If your HTTP/2 pseudo-headers are in the wrong order, your regular headers are sorted alphabetically, or your TLS client does not look like Chrome, you are going to have a bad time against modern antibots. DataDome is no exception.
We have separate docs that cover those basics:
But there is a second problem that catches a lot of people after they fix TLS and header order:
If you mimic headers from a browser session that was not recorded correctly, you will still get blocked.
That is the part people underestimate. They open a browser, record a DataDome flow, copy the headers, and assume those headers are the source of truth. But if the browser profile already had state, or the recording happened in incognito, the capture is already polluted. You are not copying a clean browser flow. You are copying the side effects of the way you recorded it.

At Hyper Solutions, we handle the DataDome sensor data and telemetry required for these flows. But your request flow still needs to be recorded from the right browser context. If your headers say one thing and the sensor payload says another, DataDome can block the session even when the request looks close in an HTTP debugger.
The Real Mistake: Bad Recording State
Most bad DataDome implementations do not start with bad code. They start with a bad browser recording.
Two mistakes show up constantly:
- Recording in incognito
- Clearing only cookies instead of clearing the full Chrome profile state
Both mistakes create headers that look real because they came from Chrome. But they are not the headers you should be hardcoding into a clean request-based flow.
The browser was in the wrong state when you recorded it.
That matters because DataDome is not only looking at header order. It is comparing the full request flow against browser-side signals: Client Hints, cookies, storage access state, language state, device properties, and the generated sensor payload.
Small inconsistencies are enough to turn a "matches exactly" debugger comparison into a hard block.
Quick Detour: What Client Hints Are
Client Hints are browser-generated HTTP request headers that expose selected details about the browser, device, platform, and network in a more structured way than the old User-Agent string.
You have probably seen headers like:
sec-ch-ua: "Google Chrome";v="149", "Chromium";v="149", "Not_A Brand";v="24"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Those are Client Hints. Some low-entropy hints can appear by default in Chromium traffic.
More detailed hints, such as architecture, model, full version list, and device memory, are usually sent only after the server asks for them or after the browser exposes related values through JavaScript APIs such as navigator.userAgentData.
That is why Client Hints matter so much in DataDome flows. The HTTP headers and the JavaScript-generated sensor payload describe the same browser from two different angles.
If you copy Client Hint headers from a polluted browser capture, but your DataDome sensor payload describes a different browser state, the request starts contradicting itself.
Mistake 1: Recording In Incognito
Incognito feels like a clean browser. It is not.
For DataDome work, incognito is a different browser context with different observable behavior.
If you record in incognito and then try to build a normal-browser request flow, you can end up copying headers and signals that do not match the sensor payload you actually use.
One common example is Sec-Fetch-Storage-Access.
In the DataDome flows we are talking about here, this header is sent on the geo.captcha-delivery.com requests.
Those requests go to DataDome's captcha/challenge delivery origin, and Chrome includes fetch metadata so the server can understand the request context. Sec-Fetch-Storage-Access specifically tells the server whether the current fetch has access to unpartitioned third-party cookie storage.
In a normal browser flow, that value should match the browser context that produced the DataDome payload. In incognito captures, the geo.captcha-delivery.com requests consistently show:
Sec-Fetch-Storage-Access: none
That does not mean your normal-browser DataDome flow should hardcode Sec-Fetch-Storage-Access: none. It means the request was recorded in incognito.

There are other incognito signals too. In observed DataDome challenge behavior, DataDome checks whether a test cookie can be written and read. In a normal browser context, that check returns true. In incognito-like contexts, it can return false.
Language state can differ as well. A normal browser might expose:
["en-US", "en"]
An incognito context may expose only:
["en-US"]
Those differences are small, but DataDome is built to care about small differences.
This is why people often get blocked more while recording from incognito. The payload itself can contain incognito-like signals. Then the developer copies headers from that recording, uses normal-browser sensor data later, and ends up with a mixed story:
- The request headers say incognito-like context.
- The sensor data says normal browser.
- The cookies and challenge state come from another flow.
- The header order looks correct, so the mistake is easy to miss.
DataDome does not need one giant contradiction. A few small contradictions are enough.
If you are trying to model a normal browser, do not record the flow in incognito.
Mistake 2: Clearing Cookies But Not Full Browser State
The second mistake is even more common.
A client records a DataDome flow, hits a hard challenge, and Chrome receives an Accept-CH response header. Then the client wants to record a fresh flow, so they clear cookies and try again.
That sounds reasonable, but it is not enough.
Accept-CH is a response header that tells the browser which Client Hints the server wants on later requests. DataDome commonly includes hints such as:
Accept-CH: Sec-CH-UA,Sec-CH-UA-Mobile,Sec-CH-UA-Platform,Sec-CH-UA-Arch,Sec-CH-UA-Full-Version-List,Sec-CH-UA-Model,Sec-CH-Device-Memory
Once Chrome has seen that, it can remember the Client Hint opt-in for the profile. Clearing cookies does not necessarily reset that browser profile state.
So the next recording starts with a trap:
- You record a DataDome hard challenge.
- DataDome returns
Accept-CH. - Chrome remembers that the origin asked for extra Client Hints.
- You clear cookies.
- You record again in the same profile.
- Extra
Sec-CH-*headers appear on the first request. - You copy those headers into your request flow.
Now your first request includes values that should not be there in a clean first request.

This is where people get burned by headers like:
sec-ch-ua-archsec-ch-ua-full-version-listsec-ch-ua-modelsec-ch-device-memory
If those show up before the flow has actually reached the DataDome step that requests them, you are not looking at a clean first request. You are looking at browser profile pre-state.
That creates mismatches fast.
For example, your first request might include one full Chrome version from the stale Client Hint state, while the later DataDome payload or API-generated sensor data contains another. The values look very close in a debugger, but they do not describe the same browser session.
The obvious question is:
How can your request know the full version before hitting the API or challenge flow that dynamically returns the matching values?
It cannot.
If the value is present because a previous browser recording left state behind, hardcoding it into the request client will only make the mismatch permanent.
The fix is not to copy more headers. The fix is to record the flow properly.
Use a new Chrome profile, or remove all-time browser history and site data before recording. Do not just clear cookies for the target domain. You want the first request in your debugger to represent a real first request from a clean browser profile.

Headers And Sensor Data Must Tell The Same Story
DataDome's client-side checks collect browser, device, and behavior-related signals. That includes values exposed through browser APIs such as navigator.userAgentData, navigator.deviceMemory, navigator.languages, navigator.hardwareConcurrency, navigator.platform, viewport properties, touch support, online state, and webdriver indicators.
Those values need to line up with the HTTP layer.
If your headers say:
- Chrome version A
- Normal browsing context
- Specific platform and architecture
- Certain Client Hints already available
Then the DataDome sensor payload should not say:
- Chrome version B
- Incognito-like storage or cookie behavior
- Different language state
- Different platform or device properties
- Client Hint values generated at a later point in the flow
This is the core reason polluted captures are so dangerous. They make wrong values look official because they came from Chrome.
But Chrome in the wrong state is still the wrong source of truth.
How To Record A Cleaner DataDome Flow
When you record a DataDome-protected flow for a request-based implementation:
- Start from a new Chrome profile when possible.
- If reusing a profile, remove all-time browser history, cookies, cache, and site data before recording.
- Do not record a normal-browser flow in incognito.
- Do not treat a cookie clear as a full browser reset.
- Watch the first request carefully for unexpected
Sec-CH-*headers. - Treat
Sec-Fetch-Storage-Access: nonefrom incognito as an incognito signal, not a universal requirement. - Do not hardcode high-entropy Client Hints just because they appeared in a polluted capture.
- Compare the HTTP headers against the sensor payload values, not only against another header list.
The point is not to make your request template longer. The point is to make the flow coherent.
Where Hyper Solutions Fits
If you are looking to get around DataDome from a request-based setup, you need more than copied headers.
You need the DataDome sensor data, challenge telemetry, and request flow to agree with each other. That is what Hyper Solutions provides. Our API returns the dynamic sensor data needed for DataDome flows, so you do not have to guess or hardcode browser-derived values from a polluted recording.
But the capture still matters. If you record in incognito, or reuse a Chrome profile that remembers Accept-CH, you can build mismatches into your flow before our sensors ever enter the picture.
Record from a clean normal Chrome profile. Keep the headers and payload aligned. Let Hyper Solutions handle the DataDome sensor data.
If you are working on DataDome-protected targets and want reliable request-based flows, register at hypersolutions.co.