     [Blog](https://scrapfly.io/blog)   /  [blocking](https://scrapfly.io/blog/tag/blocking)   /  [How to Bypass Datadome Anti Scraping in 2026](https://scrapfly.io/blog/posts/how-to-bypass-datadome-anti-scraping)   # How to Bypass Datadome Anti Scraping in 2026

 by [Ziad Shamndy](https://scrapfly.io/blog/author/ziad) Oct 18, 2026 29 min read [\#blocking](https://scrapfly.io/blog/tag/blocking) 

 [  ](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-bypass-datadome-anti-scraping "Share on LinkedIn") [  ](https://x.com/intent/tweet?url=https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-bypass-datadome-anti-scraping&text=How%20to%20Bypass%20Datadome%20Anti%20Scraping%20in%202026 "Share on X") [  ](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-bypass-datadome-anti-scraping "Share on Facebook")    

 

 

Summarize this article with

 [  ](https://chat.openai.com/?q=Summarize%20this%20article%20and%20explain%20how%20Scrapfly%20helps%20me%20scrape%20any%20website%20at%20scale%20and%20bypass%20anti-bot%20systems%20for%20my%20use%20case%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-bypass-datadome-anti-scraping) [  ](https://claude.ai/new?q=Summarize%20this%20article%20and%20explain%20how%20Scrapfly%20helps%20me%20scrape%20any%20website%20at%20scale%20and%20bypass%20anti-bot%20systems%20for%20my%20use%20case%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-bypass-datadome-anti-scraping) [  ](https://x.com/i/grok?text=Summarize%20this%20article%20and%20explain%20how%20Scrapfly%20helps%20me%20scrape%20any%20website%20at%20scale%20and%20bypass%20anti-bot%20systems%20for%20my%20use%20case%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-bypass-datadome-anti-scraping) [  ](https://www.perplexity.ai/search/new?q=Summarize%20this%20article%20and%20explain%20how%20Scrapfly%20helps%20me%20scrape%20any%20website%20at%20scale%20and%20bypass%20anti-bot%20systems%20for%20my%20use%20case%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-bypass-datadome-anti-scraping) [  ](https://www.google.com/search?udm=50&aep=11&q=Summarize%20this%20article%20and%20explain%20how%20Scrapfly%20helps%20me%20scrape%20any%20website%20at%20scale%20and%20bypass%20anti-bot%20systems%20for%20my%20use%20case%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-bypass-datadome-anti-scraping) 



   

DataDome is a popular anti-bot service that websites like [How to Scrape Leboncoin.fr in 2026 (No API Needed)](https://scrapfly.io/blog/posts/how-to-scrape-leboncoin-marketplace-real-estate) use to block bots, such as web scrapers. Each customer gets its own detection model, so a scraper that passes one DataDome site can fail on another.

In this article, we'll explain how to identify DataDome and how it detects web scrapers. Then, we'll take a look at bypassing it with `curl_cffi`, Nodriver, SeleniumBase and Camoufox, and where each tool stops. Let's dive in!



## What Is DataDome?

DataDome is a WAF service that is used to protect websites from bad bots, fraud and DDoS attacks. Web scrapers are bots too, so they can get detected and blocked by DataDome as well.

The way DataDome works can be explained in three steps:

- The website's server **asks DataDome to evaluate each incoming request** through a module installed on its CDN or web server.
- In the browser, the website loads DataDome's [JavaScript Tag](https://docs.datadome.co/docs/javascript-tag), usually from `js.datadome.co/tags.js`. It **collects details about the browser and the device** and sends them to DataDome.
- Based on this data, DataDome either **allows the request, blocks it or sends a challenge** that has to be passed first.

The server module is available for many platforms, such as Cloudflare Workers, AWS CloudFront, Fastly, Apache and HAProxy, and the full list can be found in [DataDome's integration docs](https://docs.datadome.co/docs/platform-integrations-server-side/llms.txt).

This means that a website can run DataDome on another provider's CDN, and its response headers can show Cloudflare or CloudFront even though the request is blocked by DataDome.

So, it's better to identify DataDome using its cookie and challenge page instead of the response headers. For other anti-bot services, refer to our guide on [identifying anti-bot services](https://scrapfly.io/blog/posts/how-to-know-what-anti-bot-website-uses).



## How Do You Know a Site Uses DataDome?

When a request is blocked by DataDome, the response can have a 403 status code and a short page instead of the requested content. However, the status code alone isn't enough, as other anti-bot services return 403 errors too.

To confirm it's DataDome, we can open the browser's network tab and inspect the blocked response. DataDome leaves a few traces there, and most of them can be found in raw HTTP responses as well.

Here are the common signs of DataDome blocking:

- `datadome` cookie with a [one-year expiration](https://docs.datadome.co/docs/cookie-session-storage).
- `js.datadome.co/tags.js` script loaded on normal pages, or a first-party path on websites that proxy it.
- Challenge scripts loaded from `ct.captcha-delivery.com`.
- Challenge pages framed from `*.captcha-delivery.com`.
- 403 status code with a short HTML page.

These `captcha-delivery.com` hosts are the same ones that DataDome's [JavaScript Tag docs](https://docs.datadome.co/docs/javascript-tag) ask website owners to allow in their Content Security Policy. So, if they show up in the network tab, it's a clear sign of DataDome.

The DataDome block page can either ask the visitor to wait or show a CAPTCHA challenge. For example, here's what it looks like on Leboncoin:



This block is often encountered on the first request to the website. That being said, DataDome can also allow a few requests and then challenge the session later, after analyzing the client's behavior.

If it's still not clear which anti-bot service is used, the [Scrapfly Antibot Detector](https://scrapfly.io/products/antibot-detector) can check the URL for us. Also, 403 errors have other causes too, which are covered in our [403 guide](https://scrapfly.io/blog/posts/403-forbidden-web-scraping).

Next, let's have a closer look at how DataDome's challenges work.

[5 Proven Ways to Bypass CAPTCHA in Python for 2026Captchas can ruin web scrapers but we don't have to teach our robots how to solve them - we can just get around it all!](https://scrapfly.io/blog/posts/how-to-bypass-captcha-web-scraping)



## How Does DataDome Detect Web Scrapers?

To detect web scrapers, DataDome combines details of the request itself, like the IP address, TLS handshake and HTTP details, with everything the JavaScript Tag collected in the browser.

These are combined into a score, and according to the [detection engine description](https://datadome.co/ai-detection-engine/), that score can change during the session. Based on it, DataDome allows the request, blocks it or serves one of the challenges above.

This process can seem complex and daunting, but each layer can be addressed on its own once we know what it looks at. Let's take a look at each of them.

### TLS and JA3/JA4 Fingerprinting

The first step is the TLS handshake, which is how the client and the server negotiate an HTTPS connection. Chrome negotiates differently from a Python HTTP library, so the handshake can give a scraper away even when the User-Agent matches.

JA3 and JA4 are fingerprints that summarize this handshake, and our [JA3 and JA4 guide](https://scrapfly.io/blog/posts/ja3-ja4-tls-fingerprinting-guide-to-detection-and-evasion) explains both formats. To see what our own client is sending, we can use the [JA3 tool](https://scrapfly.io/web-scraping-tools/ja3-fingerprint).

### IP Address and Residential Proxy Checks

The IP address is the next detail DataDome analyzes. Each IP address carries some metadata about the connecting client, such as its geographical location, the ISP or network that owns it and its reputation.

DataDome also checks the IP address type. Currently, IP addresses are categorized into three types based on their issuer:

- **Residential**IP addresses assigned by ISPs to home internet connections. Since they're used by real people, their traffic looks like ordinary visitors, which gives them a positive trust score.
- **Mobile**IP addresses assigned by carrier networks to mobile devices. These addresses may be shared by many devices, making them harder to track and block.
- **Datacenter**IP addresses that belong to hosting infrastructure, such as cloud providers. As they are rarely used by real users, they are easier to classify as automated traffic.

So, it's recommended to **use residential or mobile proxies** when scraping DataDome-protected websites. That being said, residential proxies aren't a guaranteed solution, as DataDome has published research on detecting residential proxies using machine learning.

In other words, the IP address is only one part of the trust score, and the rest of the request details have to look natural as well.

### HTTP/2 and Header Details

After the IP address, DataDome analyzes the HTTP request details. Currently, most web browsers communicate over the **HTTP/2** and **HTTP/3** protocols, while many HTTP clients still use HTTP/1.1 by default (such as Python's `requests`).

Even if the HTTP client supports HTTP/2, it can still be identified through **HTTP/2 fingerprinting**. This is because the HTTP/2 connection settings and the request header order can be different from those of a real web browser.

For example, let's say we are using a Python HTTP client with a Chrome User-Agent string. Despite the User-Agent, DataDome can still tell that it's not Chrome, as the TLS and HTTP details don't match the ones Chrome sends.

To avoid this, **make sure your HTTP client supports HTTP/2 and sends its headers in the same order as a real browser**. You can test your HTTP/2 fingerprint using ScrapFly's HTTP/2 fingerprint tool.

For more details on HTTP/2 fingerprinting, refer to our previous guide on HTTP/2 and HTTP/3 fingerprinting.

### JavaScript Fingerprinting and the DataDome JS Tag

JavaScript fingerprinting is the most advanced technique used by DataDome. In essence, when the page loads, DataDome's JavaScript Tag runs in the browser and collects details about the client's environment.

Let's break down the main data points it collects:

- Web browser details
- Operating system information
- GPU details
- How the page is being used

The collected data is then combined to create a unique fingerprint of the client. Moreover, the Device Check and the Slider challenges run their own JavaScript checks on top of it.

Since HTTP clients like `requests` can't execute JavaScript, they can't send this data at all. Hence, they are easily flagged by DataDome.

Some bypass tools try to generate this data without running a browser. However, since June 2026, DataDome's proof of browser check makes this approach much harder to pull off.

Therefore, the most reliable way to deal with JavaScript fingerprinting is to **use a real web browser**. However, browser automation tools can leak their own automation signals, which we'll explore in the tools section.

### DataDome Behavior Analysis

Behavior analysis is used by DataDome to track how the client interacts with the website. For instance, the JavaScript Tag records mouse and keystroke activity, as stated in its documentation.

This allows DataDome to keep evaluating the session, even after the client passes all of the previous checks. Here are some common browsing patterns that can make a real browser look automated:

- Visiting deep URLs one after another without navigating the website.
- Waiting for the exact same interval between every request.
- Changing the browser profile in the middle of the session.

To avoid this, **keep one browser profile tied to one proxy for the whole session**, and try to browse the website the same way a normal user would.

### DataDome Per-Customer ML Models

DataDome relies on machine learning models to analyze all of the above data. These models aren't the same for all websites, as they're tailored to each customer and use case. DataDome also offers what it calls intent-based detection.

According to DataDome's AI detection engine page, it runs over 85,000 models and 300,000 rules. It also processes five trillion signals per day, with a response time of under two milliseconds (these numbers are DataDome's own claims).

This means that each website can react differently to the same scraper. In other words, a setup that works fine on one DataDome-protected website can still get challenged on another one.

#### What This Means for Scrapers

Now that we have an overview of how DataDome detects web scrapers, let's summarize what to keep in mind while scraping DataDome-protected websites:

- Test your target website directly, as passing another DataDome website doesn't mean this one will pass as well.
- Keep the IP address, cookies, browser profile and browsing pattern consistent during the whole session.
- Check every response you receive, as getting the real content on the first page doesn't guarantee the next pages.

For more on these detection techniques, refer to our previous guide on bypassing anti-bot protection. Next, let's explore the available tools for bypassing DataDome.



Scrapfly

#### Need to bypass anti-bot protection?

Scrapfly's Unblocker handles Cloudflare, DataDome, and more — automatically.

[Try Free →](https://scrapfly.io/register)## How to Bypass DataDome: curl\_cffi, Nodriver, SeleniumBase and Camoufox

Now that we have covered how DataDome detects web scrapers, let's take a look at the tools we can use to bypass it. Since all of these layers are combined into one score, fixing just one of them isn't enough.

In essence, our scraper has to look like a real web browser running on a residential IP address. That IP should stay the same for the whole session, and the browser's language, location and fingerprint should all match it.

A browser like this can complete the Device Check by itself, but the Slider still needs a human to drag the puzzle piece. Also, DataDome tailors its models to each customer, so no setup works on every website.

Currently, there are three types of tools we can use for this:

- **HTTP clients**Libraries like `curl_cffi`, which copy the TLS and HTTP/2 details of a real web browser. They are lightweight, but they cannot execute JavaScript.
- **Stealth browsers**Nodriver, SeleniumBase CDP Mode and Camoufox. These run a real browser engine, so the DataDome scripts get executed the same way as on a normal visit.
- **Web scraping APIs**Scrapfly's Web Scraping API, which manages the proxies, the browser and the challenges for us.

Which tool to use depends on what the target website sends back, as there is no point in running a full browser for a page that a plain HTTP request can already get.

But what about popular browser automation tools, like [Playwright](https://playwright.dev/), [Puppeteer](https://pptr.dev/) and [Selenium](https://www.selenium.dev/)? Out of the box, these tools can leak the `navigator.webdriver` property, which marks the browser as automated.

There are patches that hide these leaks (e.g., [Playwright Stealth: Bypass Bot Detection in Python &amp; Node.js](https://scrapfly.io/blog/posts/playwright-stealth-bypass-bot-detection), [Puppeteer Stealth: Complete Guide to Avoiding Detection](https://scrapfly.io/blog/posts/puppeteer-stealth-complete-guide) and [Web Scraping Without Blocking With Undetected ChromeDriver](https://scrapfly.io/blog/posts/web-scraping-without-blocking-using-undetected-chromedriver)). That being said, the DataDome [JavaScript Tag docs](https://docs.datadome.co/docs/javascript-tag) mention that it checks for modified automation tools as well.

Let's start by comparing these tools.

### Which DataDome Bypass Tool Fixes Which Layer?

Before jumping into the code, here is how each tool compares, along with the version we'll be using in our examples:

| Tool | What it changes | Runs page JavaScript | Browser engine | Built-in DataDome Slider handling |
|---|---|---|---|---|
| `curl_cffi` 0.16.3 | TLS and HTTP/2 fingerprint | No | None | No |
| Nodriver 0.50.3 | Removes WebDriver signals (CDP only) | Yes | Chrome | No |
| SeleniumBase 4.54.13 CDP Mode | Disconnects WebDriver during checks | Yes | Chrome | No |
| Camoufox 0.5.6 | Spoofs fingerprint values in the engine | Yes | Firefox | No |
| Scrapfly Web Scraping API (Unblocker) | Proxy, browser and headers, managed | When needed | Managed | Managed by Scrapfly |

From the above, we can see that `curl_cffi` is the only tool that can't run JavaScript. This means it only works as long as DataDome returns the real page, and any challenge has to be handled by a browser.

On the other hand, none of the browsers can solve the Slider by themselves. So, if you keep getting the Slider on every request, the first things to check are the IP address and the browser profile.

Since every one of these tools sends its requests from an IP address that DataDome scores, let's set up the proxies first.

### Start With Sticky Residential Proxies

As we have seen in the IP address section, residential and mobile IP addresses are harder for DataDome to flag than datacenter ones. Therefore, **residential or mobile proxies** are the way to go for DataDome-protected websites.

Rotating the IP address with every request is a common way to avoid IP blocking. However, it backfires with DataDome, since requests from the new IP address would still carry the `datadome` cookie from the old one.

Instead, you should use **sticky sessions**, where the proxy keeps the same IP address for the whole browsing session and only switches to a new one when a new session starts.

The proxy location matters as well. For instance, a German IP address with a browser in US English and a New York timezone is an obvious mismatch, so the timezone, locale and `Accept-Language` header should all follow the proxy's country.

Camoufox can take care of this using its [geoip option](https://camoufox.com/python/geoip/), which picks the location and locale based on the proxy IP address. As for Scrapfly, all requests are sent through proxies by default.

[The Complete Guide To Using Proxies For Web ScrapingIntroduction to proxy usage in web scraping. What types of proxies are there? How to evaluate proxy providers and avoid common issues.](https://scrapfly.io/blog/posts/introduction-to-proxies-in-web-scraping)

With the proxies covered, let's start with the lightest tool on our list, `curl_cffi`!

### Use curl\_cffi for DataDome's TLS and HTTP/2 Checks

`curl_cffi` is a Python HTTP client with an API similar to the popular `requests` library. Under the hood, it uses curl-impersonate, which mimics the TLS handshake and HTTP/2 settings of real web browsers.

This way, our requests look like real browser traffic at the network level. That being said, \_\_`curl_cffi` can't execute JavaScript\_\_, so it can't solve the DataDome challenges and only works when the website returns the real page.

It can be installed using the following `pip` command. In this guide, we'll be using version 0.16.3:

bash

```bash
pip install curl_cffi
```



To impersonate a browser, all we have to do is pass the `impersonate` parameter. Setting it to `"chrome"` uses a recent Chrome profile, and for a specific version (e.g., `chrome142`), refer to the [target list](https://curl-cffi.readthedocs.io/en/latest/impersonate/targets.html).

Let's use it to send a request to `web-scraping.dev` and check the response for DataDome:

python

```python
from curl_cffi import requests

# DataDome's challenge pages load their scripts from this host (per DataDome's JS Tag docs)
CHALLENGE_HOST = "captcha-delivery.com"


def is_datadome_challenge(html):
    """True when the HTML is a DataDome challenge page instead of content."""
    return CHALLENGE_HOST in html


def fetch(url):
    # a Session keeps cookies, including datadome, between requests
    with requests.Session(impersonate="chrome") as session:
        response = session.get(url, timeout=30)
        print("status:", response.status_code)
        print("datadome cookie set:", "datadome" in session.cookies)
        print("challenge page:", is_datadome_challenge(response.text))
        return response


if __name__ == "__main__":
    fetch("https://web-scraping.dev/products")
```



Here, we create a `Session` with Chrome impersonation, which keeps the cookies between requests. Then, we send a GET request and print the status code, whether the `datadome` cookie was set and whether we got a challenge page.

The challenge check is done by the `is_datadome_challenge()` function. It simply looks for `captcha-delivery.com` in the HTML, since the DataDome challenge pages load their scripts from this host. Here is what we got:

text

```text
status: 200
datadome cookie set: False
challenge page: False
```



We can see that the page loaded normally and no `datadome` cookie was set. That is expected, as `web-scraping.dev` is a test website by Scrapfly that doesn't use DataDome.

However, when running the same code against a real DataDome-protected website, a `True` challenge flag means we got a challenge page instead of the data, so the response shouldn't be parsed and the URL should be retried with a browser.

Note that the User-Agent has to match the impersonated browser. The `impersonate` parameter already sets the matching headers for us, so it is better to leave them as they are. For more details, refer to our [curl-impersonate guide](https://scrapfly.io/blog/posts/curl-impersonate-scrape-chrome-firefox-tls-http2-fingerprint).

We have seen that `curl_cffi` makes our requests look like Chrome, but it can't execute JavaScript. Let's look at a tool that can, Nodriver!

### Try Nodriver

Nodriver is the successor of undetected-chromedriver and is developed by the same author. Unlike undetected-chromedriver, it doesn't rely on a patched ChromeDriver. Instead, it drops WebDriver completely and controls Chrome using the Chrome DevTools Protocol (CDP).

In essence, since there is no WebDriver connection, the browser doesn't leak any of the WebDriver signals. Nodriver is also fully asynchronous, so our code will be using `async` and `await`.

#### Nodriver Example

Nodriver can be installed using `pip`. Since our example uses the 0.50.3 API, let's pin that exact version:

bash

```bash
pip install nodriver==0.50.3
```



Next, let's use Nodriver to open Scrapfly's browser fingerprint tool and run the same DataDome checks:

python

```python
import nodriver as uc


def is_datadome_challenge(html):
    """True when the HTML is a DataDome challenge page instead of content."""
    return "captcha-delivery.com" in html


async def main():
    browser = await uc.start()
    page = await browser.get("https://scrapfly.io/web-scraping-tools/browser-fingerprint")

    # wait for the page to fully load and any challenges to complete
    await page.sleep(5)

    # save screenshot to verify fingerprint obfuscation
    await page.save_screenshot("fingerprint.png", format="png")

    # check the result for DataDome's challenge page and cookie
    content = await page.get_content()
    cookies = await browser.cookies.get_all()
    print("challenge page:", is_datadome_challenge(content))
    print("datadome cookie set:", any(c.name == "datadome" for c in cookies))

    browser.stop()

if __name__ == "__main__":
    uc.loop().run_until_complete(main())
```



Here, we start Chrome with `uc.start()` and open the fingerprint tool. After five seconds, we take a screenshot and get the HTML and cookies using `get_content()` and `browser.cookies.get_all()`. Here is what we got:

text

```text
challenge page: False
datadome cookie set: False
```



As expected, there is no challenge, since the fingerprint tool isn't protected by DataDome. The useful part here is the screenshot, which shows how the browser fingerprint looks to websites.

When you move to a real target, **avoid headless mode and stick to one proxy for the whole browser session**.

[Web Scraping Without Blocking With Undetected ChromeDriverIn this tutorial we'll be taking a look at a new popular web scraping tool Undetected ChromeDriver which is a Selenium extension that allows to bypass many scraper blocking techniques.](https://scrapfly.io/blog/posts/web-scraping-without-blocking-using-undetected-chromedriver)

Nodriver only comes with an async API, though. If you're more familiar with Selenium, SeleniumBase is the next tool to try.

### Try SeleniumBase CDP Mode

SeleniumBase is a framework built on top of Selenium, and it comes with two modes for avoiding bot detection:

- **UC Mode**Disconnects WebDriver from the browser while the anti-bot checks are running.
- **CDP Mode**Controls the page using the Chrome DevTools Protocol instead of WebDriver, similar to Nodriver.

SeleniumBase also has helper methods for handling other CAPTCHA types. However, there isn't one for the DataDome Slider. For more on SeleniumBase, refer to our [SeleniumBase guide](https://scrapfly.io/blog/posts/guide-to-seleniumbase-better-selenium).

#### SeleniumBase CDP Mode Example

The methods used in this example are covered in the [CDP Mode documentation](https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/ReadMe.md). First, let's install SeleniumBase 4.54.13, which is the version we tested this example with:

bash

```bash
pip install seleniumbase==4.54.13
```



Then, let's open the fingerprint tool again, this time using CDP Mode:

python

```python
from seleniumbase import SB


def is_datadome_challenge(html):
    """True when the HTML is a DataDome challenge page instead of content."""
    return "captcha-delivery.com" in html


with SB(uc=True, test=True, locale="en") as sb:
    # activate CDP mode for Datadome-protected sites
    sb.activate_cdp_mode("https://scrapfly.io/web-scraping-tools/browser-fingerprint")
    sb.sleep(5)

    # save screenshot to verify fingerprint obfuscation
    sb.save_screenshot("fingerprint.png")

    # evaluate JavaScript to get the page title
    title = sb.cdp.evaluate("document.title")
    print(title)

    # check the result for DataDome's challenge page and cookie
    html = sb.cdp.get_page_source()
    cookies = sb.cdp.get_all_cookies()
    print("challenge page:", is_datadome_challenge(html))
    print("datadome cookie set:", any(c.name == "datadome" for c in cookies))
```



Here, we start SeleniumBase with `uc=True` and use `activate_cdp_mode()` to open the target page in CDP Mode. After waiting for five seconds, we save a screenshot and get the page title by running `document.title` through `sb.cdp.evaluate()`.

Finally, we pass the HTML from `get_page_source()` to our challenge check and look for the `datadome` cookie in `get_all_cookies()`. Here is the output:

text

```text
Browser Fingerprint Test - Detect Your Unique Browser Signature
challenge page: False
datadome cookie set: False
```



The title shows that the fingerprint tool loaded normally. Just like with Nodriver, CDP Mode runs the page's JavaScript, but the Slider would still need someone to drag it.

Both Nodriver and SeleniumBase are based on Chrome. Next, let's try a different browser engine with Camoufox!

### Try Camoufox

Camoufox works differently from the Chrome-based tools we have used so far. It's a custom Firefox build that spoofs the fingerprint values inside the browser itself, instead of injecting JavaScript overrides into the page.

To generate these fingerprints, Camoufox uses [BrowserForge](https://github.com/daijro/browserforge). However, the values still have to make sense together, and the README warns about mismatches (e.g., a Windows User-Agent paired with a GPU that only exists on macOS).

#### Camoufox Example

Let's start by installing Camoufox 0.5.6 with GeoIP support. The Python package doesn't come with the browser itself, as the [browser builds](https://camoufox.com) are published separately. So, we also have to download one with the `fetch` command:

bash

```bash
pip install "camoufox[geoip]==0.5.6"
python -m camoufox fetch
```



Once the download is done, let's run the same checks with Camoufox:

python

```python
from camoufox.sync_api import Camoufox


def is_datadome_challenge(html):
    """True when the HTML is a DataDome challenge page instead of content."""
    return "captcha-delivery.com" in html


with Camoufox(
    headless=False,     # a visible window instead of headless mode
    humanize=True,      # human-like cursor movements
    os="windows",       # generate Windows fingerprints
    geoip=True,         # auto-spoof location from proxy IP
) as browser:
    page = browser.new_page()
    page.goto("https://scrapfly.io/web-scraping-tools/browser-fingerprint")
    page.wait_for_timeout(5000)

    # save screenshot to verify fingerprint obfuscation
    page.screenshot(path="fingerprint.png")

    # check the result for DataDome's challenge page and cookie
    html = page.content()
    cookies = page.context.cookies()
    print("challenge page:", is_datadome_challenge(html))
    print("datadome cookie set:", any(c["name"] == "datadome" for c in cookies))
```



Let's break down the parameters we passed to Camoufox:

- `headless=False`: opens a visible Firefox window instead of running in headless mode.
- `humanize=True`: makes the cursor movements look human-like.
- `os="windows"`: generates Windows fingerprints.
- `geoip=True`: sets the location from the proxy IP address. Since we don't use a proxy here, our machine's own IP address is used instead.

After the page loads, we take a screenshot and get the HTML with `page.content()`. The cookies come from `page.context.cookies()` as a list of dictionaries, so we check each one's `name` key. Here is what we got:

text

```text
challenge page: False
datadome cookie set: False
```



We can see the same result as with the Chrome-based tools, as there's no DataDome on this page.

[Best Stealth Browsers for Web Scraping in 2026A neutral, benchmark-literate ranking of the best open-source stealth browsers for web scraping in 2026, with the success, speed, and maintenance tradeoffs.](https://scrapfly.io/blog/posts/best-stealth-browsers)

Running a full browser for every page is slow and heavy on resources, though. So, what about using the browser only to get the `datadome` cookie and sending the rest of the requests with `curl_cffi`?

### Can You Reuse a Browser datadome Cookie in curl\_cffi?

Yes, it's possible, though it might not last for long. According to the DataDome [cookie docs](https://docs.datadome.co/docs/cookie-session-storage), the cookie is shared by the server-side check and the browser check, and every request that carries it still gets scored.

This means that the cookie alone isn't enough, and our `curl_cffi` requests have to look like the browser that received it. Here are a few tips for doing that:

- Only copy cookies from a browser session that loaded the real page, not a challenge page.
- Keep the same IP address and User-Agent, and choose a `curl_cffi` target that matches the browser.
- Whenever DataDome sets a new `datadome` value, replace the old one and keep using the new one.
- Once a challenge page comes back, stop retrying with `curl_cffi` and go back to the browser.

So, **keep a separate cookie jar for each browser profile and proxy**. If you'd rather not manage this yourself, Scrapfly's [session feature](https://scrapfly.io/docs/scrape-api/session) offers a managed alternative.

Cookies aren't the only thing DataDome tracks during a session, as it also looks at how the scraper moves through the website. Let's take a look at that next.

### Try Warming Up Scrapers

Since DataDome keeps scoring the session after the first request, the way our scraper browses the website matters too. For instance, real users rarely open a product URL directly, and they usually get there in a few steps:

- Open the homepage.
- Go to a product category or search for the product.
- Click through to the product page.

So, **our scraper should reach the data through the website's navigation** as well. Also, you should avoid waiting for the same amount of time between pages (e.g., exactly two seconds every time), as a fixed delay is easy to detect.

Mouse movements and scrolling can also help, especially when the page needs them to load its content. DataDome's [Slider docs](https://docs.datadome.co/docs/datadome-captcha) list mouse, touch, scroll and keystroke dynamics among the signals it collects.

With Camoufox, the [humanize option](https://camoufox.com/python/usage/) can generate these cursor movements for us. But human-like mouse movements won't do much if the IP address is already flagged or the browser profile doesn't add up.

Besides the browsing pattern, the browser profile itself should change between sessions. Let's see how to rotate it!

### Rotate Real User Fingerprints

For scrapers that run for a long time, each browser should get its own realistic profile. A browser profile is made of details like:

- Screen resolution
- Operating system
- Browser version
- Installed plugins

These values have to be consistent with each other, just like the Camoufox mismatch example we saw earlier. Also, **rotate the profiles between sessions**, as changing the profile in the middle of a session looks automated.

Before using a profile, you can check how it looks to websites with Scrapfly's [browser fingerprint tool](https://scrapfly.io/web-scraping-tools/browser-fingerprint).

Next, let's see how to troubleshoot DataDome blocks when they happen.



## Bypass DataDome with ScrapFly

Bypassing DataDome is possible, but keeping browsers, proxies and profiles consistent takes a lot of maintenance. The Scrapfly Web Scraping API can take care of the DataDome challenge flow for you once the Unblocker is enabled.

For more details, see the [DataDome bypass API](https://scrapfly.io/bypass/datadome) page for this protection and the [Web Scraping API](https://scrapfly.io/products/web-scraping-api) page for the API itself.

### Power your scraping with Scrapfly

Forget about getting blocked. Scrapfly handles anti-bot bypasses, browser rendering, and proxy rotation so you can focus on the data.



[Try for FREE!](https://scrapfly.io/register)



Note that Unblocker is the feature's current name, while Anti Scraping Protection (ASP) is the old one, which is why the SDK still uses `asp=True`.

According to the [Unblocker docs](https://scrapfly.io/docs/scrape-api/unblocker), it can switch proxy pools, turn on a browser for JavaScript, adjust headers and reuse challenge cookies within a session.

Scrapfly has SDKs for Python, TypeScript, Go and Rust. For this example, let's use the [Python SDK](https://scrapfly.io/docs/sdk/python), which can be installed using `pip`:

bash

```bash
pip install scrapfly-sdk
```



Then, all we need to do is enable the Unblocker with the `asp` parameter:

python

```python
from scrapfly import ScrapflyClient, ScrapeConfig

scrapfly = ScrapflyClient(key="YOUR_SCRAPFLY_API_KEY")
result = scrapfly.scrape(ScrapeConfig(
    url="https://web-scraping.dev/products",
    # Unblocker (formerly ASP): detects the anti-bot system and handles its challenges
    asp=True,
    # use headless browsers to render JavaScript powered pages
    render_js=True,
    # use residential proxies for higher trust scores
    proxy_pool="public_residential_pool",
))
print(result.scrape_result)
```



In this example, `asp=True` turns the Unblocker on, while `render_js` and `proxy_pool` enable JavaScript rendering and the public residential proxy pool for the Scrapfly test page.



## FAQ

Is it legal to scrape DataDome-protected pages?It depends on where you are, how you access the pages and what kind of data you collect. For example, the UK has its own computer misuse law, and collecting personal data can fall under GDPR.

In the US, the Ninth Circuit's 2022 ruling in [hiQ Labs v. LinkedIn](https://cdn.ca9.uscourts.gov/datastore/opinions/2022/04/18/17-16783.pdf) raised serious questions about applying the CFAA to public pages, though only at the preliminary injunction stage.

However, hiQ later lost a contract claim, and the case ended with a December 2022 [consent judgment](https://www.zwillgen.com/alternative-data/hiq-v-linkedin-wrapped-up-web-scraping-lessons-learned/).

Having DataDome on a website doesn't decide whether its data is private or whether scraping it is legal. Since this isn't legal advice, it's best to ask a lawyer about your specific project.







Is it possible to bypass DataDome?Yes, DataDome can be bypassed using a real browser with residential proxies and a consistent fingerprint. However, a working setup won't necessarily keep working, as DataDome keeps scoring every request and regenerates its proof of browser check with every build.

So, it's a good idea to retest the scraper whenever it starts getting challenged.







Can I bypass DataDome with Python requests?No, not on its own. The `requests` library can fetch pages that DataDome isn't challenging, but it can't complete Device Check or the Slider, as it uses HTTP/1.1, doesn't run JavaScript and has a non-browser TLS fingerprint.

A better option is [curl\_cffi](#use-curl_cffi-for-datadomes-tls-and-http2-checks), which mimics the TLS and HTTP/2 fingerprint of a real browser. Still, it can't solve challenges either, so a browser is needed once one shows up.







How long does the datadome cookie last?According to DataDome's documentation, the `datadome` cookie expires after one year. However, a valid cookie doesn't guarantee access, as DataDome still scores every request and can block or challenge it at any time.

So, the cookie is only useful as long as we're getting the real page. Once a challenge page shows up, we need the browser again to get an updated cookie.







Does Datadome block residential proxies?It can. A residential proxy alone won't get a scraper through, as DataDome still looks at the TLS fingerprint, the JavaScript checks and the browsing behavior.

DataDome has even published [research on detecting residential proxies](https://datadome.co/bot-management-protection/how-to-use-machine-learning-to-detect-residential-proxies/) using machine learning. So, it's best to keep the IP address, browser profile and cookies together for the whole session.









## Summary

In this article, we took a deep dive into DataDome anti-bot protection. We went through the details of each technique DataDome uses to detect and block web scrapers and how to avoid them. In a nutshell, these are:

- Using JA3 fingerprints that are similar to those of normal browsers with `curl_cffi`.
- Using residential or mobile proxies to hide the IP address, and keeping the same IP for the whole session.
- Using HTTP details similar to normal browsers by managing headers and enabling HTTP/2.
- Using real browsers like Nodriver, SeleniumBase and Camoufox to pass JavaScript fingerprinting and Device Check.
- Warming up scrapers and rotating browser profiles between sessions to avoid behavior analysis.

We have also seen that none of these browsers can solve the Slider by themselves, and that the 2026 proof of browser check makes solving the challenges without a browser much harder.

Finally, we've taken a look at some frequently asked questions like using Python requests against DataDome and the legality of it all.

For an easier way to handle web scraper blocking and power up your web scrapers, check out the Scrapfly [DataDome bypass API](https://scrapfly.io/bypass/datadome) for free!



 

   [  Add as a preferred source ](https://google.com/preferences/source?q=scrapfly.io) Table of Contents















 

  Table of Contents

- [What Is DataDome?](#what-is-datadome)
- [How Do You Know a Site Uses DataDome?](#how-do-you-know-a-site-uses-datadome)
- [How Does DataDome Detect Web Scrapers?](#how-does-datadome-detect-web-scrapers)
- [TLS and JA3/JA4 Fingerprinting](#tls-and-ja3-ja4-fingerprinting)
- [IP Address and Residential Proxy Checks](#ip-address-and-residential-proxy-checks)
- [HTTP/2 and Header Details](#http-2-and-header-details)
- [JavaScript Fingerprinting and the DataDome JS Tag](#javascript-fingerprinting-and-the-datadome-js-tag)
- [DataDome Behavior Analysis](#datadome-behavior-analysis)
- [DataDome Per-Customer ML Models](#datadome-per-customer-ml-models)
- [How to Bypass DataDome: curl\_cffi, Nodriver, SeleniumBase and Camoufox](#how-to-bypass-datadome-curl-cffi-nodriver-seleniumbase-and-camoufox)
- [Which DataDome Bypass Tool Fixes Which Layer?](#which-datadome-bypass-tool-fixes-which-layer)
- [Start With Sticky Residential Proxies](#start-with-sticky-residential-proxies)
- [Use curl\_cffi for DataDome's TLS and HTTP/2 Checks](#use-curl-cffi-for-datadome-s-tls-and-http-2-checks)
- [Try Nodriver](#try-nodriver)
- [Try SeleniumBase CDP Mode](#try-seleniumbase-cdp-mode)
- [Try Camoufox](#try-camoufox)
- [Can You Reuse a Browser datadome Cookie in curl\_cffi?](#can-you-reuse-a-browser-datadome-cookie-in-curl-cffi)
- [Try Warming Up Scrapers](#try-warming-up-scrapers)
- [Rotate Real User Fingerprints](#rotate-real-user-fingerprints)
- [Bypass DataDome with ScrapFly](#bypass-datadome-with-scrapfly)
- [Power your scraping with Scrapfly](#power-your-scraping-with-scrapfly)
- [FAQ](#faq)
- [Summary](#summary)
 
    Join the Newsletter  Get monthly web scraping insights 

 

  



Scale Your Web Scraping

Anti-bot bypass, browser rendering, and rotating proxies, all in one API. Start with 1,000 free credits.

  No credit card required  1,000 free API credits  Anti-bot bypass included 

 [Start Free](https://scrapfly.io/register) [View Docs](https://scrapfly.io/docs/onboarding) 

 Not ready? Get our newsletter instead. 

 

 ## Related Articles

 [     

 blocking 

### How Anti-Bot Detection Works

Discover how anti-bot systems work by assigning a 'trust score' to every request. This guide breaks down the 5 key detec...

 

 ](https://scrapfly.io/blog/posts/how-anti-bot-detection-works) [  

 blocking 

### 5 Proven Ways to Bypass CAPTCHA in Python for 2026

Captchas can ruin web scrapers but we don't have to teach our robots how to solve them - we can just get around it all!

 

 ](https://scrapfly.io/blog/posts/how-to-bypass-captcha-web-scraping) [     

 python blocking 

### How Cloudflare Detects Bots: TLS, HTTP/2, Canvas, and Turnstile Explained

Learn how Cloudflare detects bots using TLS, HTTP/2, Canvas, WebGL, behavioral analysis, and Turnstile, plus how to scra...

 

 ](https://scrapfly.io/blog/posts/how-cloudflare-detects-bots) 

  



   



 Bypass anti-bot protection automatically, **1,000 free credits** [Start Free](https://scrapfly.io/register)