In this article, we have tried to answer all the key questions. The first step in solving the task is to determine which protection system is being used. To do this, you can refer to the list of popular captchas and anti-bot protection systems, where you will find visual examples and key indicators that help you quickly understand what you are dealing with.
If you discover that your site uses DataDome CAPTCHA, the next step is to study its properties and operation in more detail. In this article, you can also review the instructions on how to integrate DataDome CAPTCHA so that you fully understand how it functions on your site. This will help you not only understand the current protection, but also properly plan its maintenance.
Working with CapMonster Cloud via API typically involves the following steps:
type - CustomTask
class - DataDome
websiteURL - the address of the main page where the CAPTCHA is solved.
captchaUrl (inside metadata) - "captchaUrl" — the link to the CAPTCHA. Usually in this format: "https://geo.captcha-delivery.com/captcha/?initialCid=..."
datadomeCookie (inside metadata) - Your DataDome cookies. Can be obtained on the page using document.cookie (if the cookies do not have HttpOnly flag), in the request header Set-Cookie: "datadome=...", or directly from the HTML code of the page initialCid.
userAgent - Browser User-Agent. Provide only the current UA from Windows OS.
Also, for this task you need to use your proxies:
proxyType :
proxyAddress - IP address of the proxy (IPv4/IPv6).
proxyPort - Proxy port.
proxyLogin - Proxy login.
proxyPassword - Proxy password.
https://api.capmonster.cloud/createTask
{
"clientKey": "API_KEY",
"task": {
"type": "CustomTask",
"class": "DataDome",
"websiteURL": "https://example.com",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36",
"metadata": {
"captchaUrl": "https://geo.captcha-delivery.com/interstitial/?initialCid=AHrlqAAAAAMA9UvsL58YLqIAXNLFPg%3D%3D&hash=C0705ACD75EBF650A07FF8291D3528&cid=7sfa5xUfDrR4bQTp1c2mhtiD7jj9TXExcQypjdNAxKVFyIi1S9tE0~_mqLa2EFpOuzxKcZloPllsNHjNnqzD9HmBA4hEv7SsEyPYEidCBvjZEaDyfRyzefFfolv0lAHM&referer=https%3A%2F%2Fwww.example.com.au%2F&s=6522&b=978936&dm=cm",
"datadomeCookie": "datadome=VYUWrgJ9ap4zmXq8Mgbp...64emvUPeON45z"
},
"proxyType": "http",
"proxyAddress": "123.45.67.89",
"proxyPort": 8080,
"proxyLogin": "proxyUsername",
"proxyPassword": "proxyPassword"
}
}
{
"errorId":0,
"taskId":407533072
}https://api.capmonster.cloud/getTaskResult{
"clientKey":"API_KEY",
"taskId": 407533072
}
{
"errorId": 0,
"status": "ready",
"solution": {
"domains": {
"www.example.com": {
"cookies": {
"datadome": "P1w0VnjFcTFslfps0J4FaPpY_QPbPBW4MeYxj4LW~pztIfJiSSuBPr8oQTUHzdrfgv137FbOBd3kCUOOgny7LhIkhm5e1qdtzYM4s2e46U_qfERK4KiCy22MOSIDsDyh"
},
"localStorage": null
}
},
"url": null,
"fingerprint": null,
"headers": null,
"data": null
}
}
// npx playwright install chromium
import { chromium } from 'playwright';
import { CapMonsterCloudClientFactory, ClientOptions, DataDomeRequest } from '@zennolab_com/capmonstercloud-client';
// Enter your CapMonster Cloud API key
const API_KEY = 'YOUR_API_KEY';
// Your site is protected by DataDome
const TARGET_URL = 'https://example.com/';
const USER_AGENT = Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)
// Proxy configuration
const proxy = {
proxyType: "http",
proxyAddress: '8.8.8.8',
proxyPort: 8080,
proxyLogin: 'proxyLogin',
proxyPassword: 'proxyPassword'
};
async function main() {
// Launch browser
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({ userAgent: USER_AGENT });
const page = await context.newPage();
// Go to the website
await page.goto(TARGET_URL, { waitUntil: 'networkidle' });
// Looking for existing datadome cookie (if any)
const existingDd = (await context.cookies()).find(c => /datadome|dd_/i.test(c.name));
// Find DataDome iframe -> CAPTCHA URL
const captchaUrl = await page.evaluate(() =>
Array.from(document.querySelectorAll('iframe[src]'))
.find(i => /captcha-delivery\.com\/captcha/i.test(i.src))
?.src || null
);
console.log(`=== Extracted DataDome parameters ===`);
console.log(`captchaUrl:`, captchaUrl || 'not found');
console.log(`current datadome cookie::`, existingDd ? ${existingDd.name}=${existingDd.value}` : 'none');
const cm = CapMonsterCloudClientFactory.Create(
new ClientOptions({ clientKey: API_KEY })
);
// Send task to CapMonster
console.log(`Sending DataDome task to CapMonster......`);
// Submitting DataDome task for solving
const solve = await cm.Solve(new DataDomeRequest({
_class: "DataDome",
websiteURL: TARGET_URL,
userAgent: USER_AGENT,
proxy,
metadata: {
captchaUrl: captchaUrl || undefined,
datadomeCookie: existingDd
? `${existingDd.name}=${existingDd.value}`
: undefined
}
}));
const sol = solve?.solution;
// Get domain and required cookies from the solution
const host = new URL(TARGET_URL).hostname;
const domainKey =
Object.keys(sol.domains).find(d => d.includes(host))
|| Object.keys(sol.domains)[0];
const cookiesArr = sol.domains[domainKey]?.cookies || [];
console.log(`\n=== Cookies from CapMonster ===`);
cookiesArr.forEach(c => console.log(`${c.name}=${c.value}`));
const ddSolved =
cookiesArr.find(c => c.name?.toLowerCase() === 'datadome')
|| cookiesArr.find(c => /datadome/i.test(c.name));
// Set datadome cookie in browser
await context.addCookies([{
name: 'datadome',
value: ddSolved.value,
domain: '.' + host,
path: '/',
httpOnly: ddSolved.httpOnly ?? true,
secure: ddSolved.secure ?? true,
sameSite: ddSolved.sameSite ?? 'Lax'
}]);
console.log(`Datadome cookie set:`, ddSolved.value);
// Reopen site after inserting cookie
const page2 = await context.newPage();
const resp2 = await page2.goto(TARGET_URL, { waitUntil: 'domcontentloaded', timeout: 60000 });
console.log(`Status after setting cookie:: ${resp2?.status()}`);
await browser.close();
}
main();
1. Log into your account or sign up with DataDome and obtain the keys (client-side and server-side).
Important: registration requires a corporate email from your company.
After registration, you will enter the admin panel.
2. Add your site (domain) in the DataDome panel.
Add your domain to the system and choose protection parameters:
3. Install server-side integration.
Use Protection API or select a ready-made module for your stack (Node.js / Express, Nginx, Cloudflare, Java (Tomcat/Jetty/Vert.x), Go, etc.).
Install the official DataDome SDK/middleware and configure the server key (server-side key).
Example of DataDome integration in Node.js:
DataDome protects the server from bots and suspicious requests, automatically showing a challenge when necessary. The module can be used with Express or the built-in HTTP server Node.js.
Installation
For Express:
npm install @datadome/module-expressFor Node.js HTTP module:
npm install @datadome/module-httpNode.js version 18 and above is supported. Server-side key from your DataDome panel is required.
const { DatadomeExpress } = require('@datadome/module-express');
const express = require('express');
const app = express();
// Initialize DataDome client
const datadomeClient = new DatadomeExpress('YOUR_SERVER_KEY');
// Connect middleware
app.use(datadomeClient.middleware());
// Your routes
app.get('/', (req, res) => {
res.send('Hello World');
});
// Start server
app.listen(3000, () => {
console.log('Server running on port 3000');
})
const { DatadomeHttp } = require('@datadome/module-http');
const http = require('http');
const datadomeClient = new DatadomeHttp('YOUR_SERVER_KEY');
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer(async (req, res) => {
const { result, error } = await datadomeClient.handleRequest(req, res);
if (result === 'ALLOW') {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\n');
} else {
console.log('Request challenged');
if (error) console.error(error);
}
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});Module settings
You can pass configuration when creating the client:
const datadomeClient = new DatadomeExpress('YOUR_SERVER_KEY', {
timeout: 150, // timeout in ms after which request is allowed
urlPatternInclusion: null, // which URLs to check
urlPatternExclusion: /\.(avi|flv|mka|mkv|mov|mp4|mpeg|mpg|mp3|flac|ogg|ogm|opus|wav|webm|webp|bmp|gif|ico|jpeg|jpg|png|svg|svgz|swf|eot|otf|ttf|woff|woff2|css|less|js|map|json|avif|xml|gz|zip)$/i,
endpointHost: 'api.datadome.co',
});Advanced options:
More details on server-side integration in official documentation.
4. Integrate client-side.
Insert JS Tag into the <head> of your website:
<head>
<script>
window.ddjskey = 'YOUR_DATADOME_JS_KEY';
window.ddoptions = {
// Add your settings here (optional)
};
</script>
<script src="https://js.datadome.co/tags.js" async></script>
<!-- Other head elements -->
</head>
YOUR_DATADOME_JS_KEY → Replace with your Client-Side key.
Load script early in <head> to allow DataDome to intercept requests and track user behavior correctly.
If using CSP, add the following directives:
<script nonce="DYNAMIC_NONCE">
window.ddjskey = 'YOUR_DATADOME_JS_KEY';
window.ddoptions = {};
</script>
script-src js.datadome.co ct.captcha-delivery.com 'nonce-DYNAMIC_NONCE';
connect-src api-js.datadome.co; /* to send JS Tag data */
frame-src *.captcha-delivery.com; /* for challenge pages */
worker-src blob:; /* for web workers */
More details on client-side integration in official DataDome CAPTCHA documentation.
Check result
DataDome creates the datadome= cookie after a successful verification. This cookie is automatically sent by the user — and the server allows the request. If the cookie is missing or invalid, DataDome will show the challenge again.
If you’ve taken over a website that already has a captcha or another protection system installed, but you don’t have access to the code, don’t worry! It’s quite easy to identify which technology is being used. To verify that everything works correctly, you can use the CapMonster Cloud recognition service in an isolated test environment to make sure that the token processing mechanism and the validation logic are functioning properly.
In the case of DataDome CAPTCHA, it’s enough to detect the system, observe its behavior, and confirm that the protection is working correctly. In this article, we showed how to identify DataDome CAPTCHA and where to find instructions on how to integrate or reconfigure it, so you can confidently maintain the protection and keep its operation under control.