# DataDome Unblocker — bypass DataDome & get clearance cookies (`xhrdev/datadome-unblocker`) Actor

Get past DataDome and keep the cookie. Returns the real page plus the datadome clearance cookie your own scraper can reuse. No browser: 4 HTTP requests, ~4 seconds. Powered by xhr.dev.

- **URL**: https://apify.com/xhrdev/datadome-unblocker.md
- **Developed by:** [xhrdev](https://apify.com/xhrdev) (community)
- **Categories:** Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$9.00 / 1,000 datadome solves

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## DataDome Unblocker

**Get past DataDome and keep the cookie.** Give this Actor a list of URLs and it returns the real page plus the `datadome` clearance cookie that unlocked it — so your own scraper can carry on from there without solving anything again.

No browser is involved. A solve is **four HTTP requests and two to five seconds**, because the challenge is solved at the payload level rather than by driving a headless Chrome through a captcha widget. That is the whole difference between this and every other anti-bot Actor on the Store.

Across repeated verification runs on Apify residential proxies, every supported site is **challenged and cleared on the first attempt**, in 2-5 seconds each.

It is powered by [**xhr.dev**](https://xhr.dev), a challenge solver that normally runs as a Docker container inside your own network. This Actor talks to a hosted trial of it, so you can try the thing before you host anything.

### Why use DataDome Unblocker?

**It gives you a cookie, not just a page.** Most bypass Actors hand back HTML and throw the session away, so every single page you want costs another full bypass. DataDome binds its clearance cookie to the IP that earned it, and this Actor returns that cookie to you — pin the same proxy session in your own crawler and one solve can cover a whole crawl. That changes the economics of scraping a protected site, not just the mechanics.

**It is fast because there is no browser.** A stealth-browser bypass spends 20–60 seconds launching Chromium, rendering a captcha, and simulating a human. This spends about four seconds making four HTTP requests. On Apify that difference is compute units, and compute units are your bill.

**It is honest about what happened.** Every dataset row says whether the URL was actually challenged, which challenge type it was, how many attempts it took, and — when it failed — *why*, as a machine-readable `errorType`. A DataDome ban on your exit IP is a different problem from a solve the site refused, and the output tells them apart instead of reporting a generic failure.

**Handles both DataDome challenge types.** The captcha (`rt: "c"`) and the interstitial (`rt: "i"`), including the case where a site escalates one into the other.

### How to use DataDome Unblocker

1. Click **Try for free**.
2. Pick the sites you want from the **Sites** dropdown. The default is Grainger, a live DataDome target you can use to watch the flow work.
3. Leave the proxy on **Apify Residential**. Do not switch it to datacenter — [it is the difference between clearing everything and clearing a quarter of it](#use-residential-proxies--this-one-is-not-optional).
4. Click **Start**. Watch the log: it names each challenge as it finds it and each solve as it lands.
5. Take the results from the **Output** tab, or pull them from the dataset API. The `cookieHeader` field is ready to send as-is.

### Input

| Field                | Type    | Default           | What it does                                                                 |
| -------------------- | ------- | ----------------- | ---------------------------------------------------------------------------- |
| `startUrls`          | array   | `grainger.com`    | The pages you want. Up to 100 per run on the shared trial solver.            |
| `proxyConfiguration` | object  | Apify Residential | Where requests leave from. **Keep this on residential** — see below.         |
| `returnHtml`         | boolean | `true`            | Include the unblocked page's full HTML. Turn off for a much smaller dataset. |
| `returnCookies`      | boolean | `true`            | Include the clearance cookie and a ready-to-send `Cookie` header.            |
| `maxRetries`         | integer | `3`               | Attempts per URL. Each takes a fresh proxy session.                          |
| `maxConcurrency`     | integer | `5`               | URLs in flight at once. Can go higher than a browser scraper would tolerate. |
| `timeoutSecs`        | integer | `120`             | Deadline for each HTTP request in the flow.                                  |

```json
{
    "startUrls": [{ "url": "https://www.grainger.com/" }],
    "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] },
    "returnHtml": false,
    "maxRetries": 3
}
```

### Output

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

```json
{
    "url": "https://www.grainger.com/",
    "succeeded": true,
    "challenged": true,
    "challengeType": "interstitial",
    "status": 200,
    "title": "Grainger Industrial Supply - MRO Products, Equipment and Tools",
    "cookies": { "datadome": "EJp800Jb_3j7j1tDAJFLE9Bk8wsBU0_prBlWFlDVhFZ..." },
    "cookieHeader": "datadome=EJp800Jb_3j7j1tDAJFLE9Bk8wsBU0_prBlWFlDVhFZ...",
    "attempts": 1,
    "durationMs": 3901,
    "error": null,
    "errorType": null
}
```

#### Data fields

| Field           | Type    | Description                                                                                                                  |
| --------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `url`           | string  | The URL that was requested.                                                                                                  |
| `succeeded`     | boolean | Whether the page was retrieved.                                                                                              |
| `challenged`    | boolean | Whether DataDome actually challenged this request. `false` is a normal, good outcome — it means your IP was already trusted. |
| `challengeType` | string  | `captcha`, `interstitial`, or `null` when unchallenged.                                                                      |
| `status`        | number  | HTTP status of the final, cleared request.                                                                                   |
| `title`         | string  | The page's `<title>`, handy for confirming you got real content.                                                             |
| `cookies`       | object  | `{ "datadome": "..." }` — the clearance cookie.                                                                              |
| `cookieHeader`  | string  | The same thing, ready to send as a `Cookie` header.                                                                          |
| `html`          | string  | Full HTML of the unblocked page, when `returnHtml` is on.                                                                    |
| `attempts`      | number  | How many tries this URL took.                                                                                                |
| `durationMs`    | number  | Wall-clock time for this URL.                                                                                                |
| `error`         | string  | Failure message, or `null`.                                                                                                  |
| `errorType`     | string  | Machine-readable reason when `succeeded` is false, or `null`.                                                      |

### Which sites are supported

You pick sites from a **dropdown**, not a free-text box. The supported set is closed, and anything outside it is refused before the run starts — so you never pay for a run against a target nobody has verified.

**Supported:** Grainger · Idealista · Etsy · Yelp · Saks Fifth Avenue · Anthropologie · Best Western · Neiman Marcus · Allegro · leboncoin

Every one is challenged and cleared on the first attempt, on every verification run.

The bar for that list is deliberately strict: the site has to be challenged *and* the challenge actually cleared, repeatedly. A site that merely returns its pages without ever being challenged does not qualify — nothing was solved, so no clearance cookie was produced, and we would rather list fewer sites than imply a capability a run never exercised.

**Need a site that is not listed?** [Tell us](https://xhr.dev) — verifying a new target is quick, and it is the most useful thing you can ask us for.

#### Using specific URLs

The dropdown runs each site's homepage. To target exact pages, put them in **Specific URLs** under Advanced; every one must sit on a supported domain.

### Use residential proxies — this one is not optional

DataDome decides **which challenge to serve based on the address you arrive from**, and that single fact governs how this Actor behaves.

Datacenter ranges are treated as suspicious and are challenged far more aggressively. Residential addresses are treated as ordinary traffic. Everything here is built and verified around a residential exit, so set the proxy to **Apify Residential** and leave it there. The Actor warns you in the log if you do not.

There is a second consequence of the same rule: **reuse the cookie from the exit IP that earned it.** DataDome binds every clearance cookie to whoever submitted it, so a `cookieHeader` taken from here and sent from somewhere else gets a fresh block that looks exactly like a failed solve. Pin the same proxy session in your own scraper.

This Actor pins a fresh proxy session per attempt automatically, so a dead exit node gets a genuinely new address rather than three tries at the same one.

### How much does it cost?

There is no browser here, so a run is cheap in Apify compute terms — the work is four HTTP requests and a wait. A solve takes about four seconds; an unchallenged URL takes under a second. Cost scales with URLs, not with page weight, and turning off `returnHtml` cuts dataset storage sharply if all you need is the cookie.

Proxy traffic is billed separately by Apify, and since residential proxies are required here, they are the larger share of the cost of any DataDome work. Residential proxy access needs a paid Apify plan.

### Tips

- **Turn off `returnHtml`** if you only want cookies. It is the single biggest reduction in dataset size.
- **Raise `maxConcurrency`** before you raise anything else. The HTTP-only path parallelises well.
- **Check `challenged` before you conclude anything about a proxy.** A run of `challenged: false` means your IPs are trusted, which is a good outcome that can be mistaken for the Actor doing nothing.
- **If results degrade, check your proxy group first.** Residential is what this Actor is verified against.
- **`errorType: "ip_banned"`** means DataDome has flagged that exit address outright (`t: "bv"`). There is no challenge to solve — rotate proxies rather than retrying.
- **`errorType: "rate_limited"`** is the shared trial solver's per-key limit, not a fault on your side. The run stops rather than burning the rest of your list; see below.

### FAQ

**Which sites does this work on?** The ten in the dropdown. The underlying solver is not site-specific — DataDome's challenge protocol is the same everywhere — but we only list targets we have actually verified, and we would rather add yours on request than claim untested coverage.

**Does it handle Akamai, Cloudflare, or PerimeterX?** Not yet. This Actor is DataDome only, deliberately, because the DataDome path needs no browser and that is where the speed advantage lives. [xhr.dev](https://xhr.dev) also solves Akamai Bot Manager, and an Akamai Actor is next.

**Why is there a 100-URL cap?** This Actor is pointed at a shared trial container, rate limited per API key. The cap keeps one run from spending everyone's budget. If you need volume, you want your own container — [get in touch](https://xhr.dev).

**Can I run the solver myself?** Yes, and that is the actual product. xhr.dev ships as a Docker container that runs on your own infrastructure: your traffic goes to the target directly, and neither your cookies nor your tokens are sent to a third party. Flat fee, unlimited solves, works air-gapped. See [xhr.dev](https://xhr.dev) and the [docs](https://docs.xhr.dev).

**Where are the integration examples?** [github.com/xhrdev/examples](https://github.com/xhrdev/examples) has the same flow written out in undici, axios, plain `fetch`, Python (requests / httpx / urllib), and curl, plus an MCP server so an LLM agent can solve a challenge inside its own loop.

**Is scraping legal?** Scraping publicly available data is broadly legal in many jurisdictions, but you are responsible for what you collect and how you use it — respect the target's Terms of Service, do not gather personal data without a lawful basis, and do not overload the sites you scrape. This Actor rate limits itself and is not built for volume abuse.

### Support

Found a bug or want a target supported? Open an issue on the **Issues** tab. For a self-hosted deployment, higher limits, or Akamai support, reach us through [xhr.dev](https://xhr.dev).

# Actor input Schema

## `sites` (type: `array`):

The DataDome-protected sites to unblock. This Actor only runs against sites it has been proven on — each one below was challenged and solved on every attempt across four consecutive verification runs. Sites that merely return a page without ever being challenged are deliberately not listed: nothing was solved, so no clearance cookie was produced, and we will not promise a capability we have not actually tested.

## `proxyConfiguration` (type: `object`):

Use RESIDENTIAL. This is not a preference — the exit address decides which challenge DataDome serves, and datacenter ranges are challenged far more aggressively. This Actor is built and verified around a residential exit. DataDome also binds every clearance cookie to the IP that earned it, so reuse the cookie from the same session. A fresh session is pinned per attempt automatically.

## `returnHtml` (type: `boolean`):

Include the full HTML of the unblocked page in each dataset item. Turn this off if you only want the cookie — it makes the dataset much smaller.

## `returnCookies` (type: `boolean`):

Include the datadome clearance cookie and a ready-to-send Cookie header. This is what lets your own scraper keep going without solving again.

## `maxRetries` (type: `integer`):

How many times to try a URL before giving up. Each attempt takes a fresh proxy session, so a dead exit node or a burnt IP gets a genuinely new chance.

## `maxConcurrency` (type: `integer`):

How many URLs to work on at once. The solve path is HTTP-only and cheap, so this can go higher than a browser scraper would tolerate.

## `startUrls` (type: `array`):

Optional. Exact pages to unblock, instead of each site's homepage. Every URL must be on one of the supported domains above, or it is refused before the run starts.

## `targetPolicy` (type: `string`):

Verified only (the default) refuses any URL outside the supported list, before the run starts, so you never pay for a run against a target nobody has checked. Allow any lifts that restriction for URLs given in "Specific URLs" — results are not guaranteed. Need a site added to the supported list? Ask at https://xhr.dev.

## `timeoutSecs` (type: `integer`):

Deadline for each individual HTTP request in the flow, including the solve itself.

## Actor input object example

```json
{
  "sites": [
    "grainger.com"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "returnHtml": true,
  "returnCookies": true,
  "maxRetries": 3,
  "maxConcurrency": 5,
  "targetPolicy": "verified-only",
  "timeoutSecs": 120
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "sites": [
        "grainger.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("xhrdev/datadome-unblocker").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "sites": ["grainger.com"] }

# Run the Actor and wait for it to finish
run = client.actor("xhrdev/datadome-unblocker").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "sites": [
    "grainger.com"
  ]
}' |
apify call xhrdev/datadome-unblocker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,xhrdev/datadome-unblocker"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/N2pNgRs5cvGfO0blS/builds/XjsWdqNQMVTLFgn38/openapi.json
