Protection API

Recent Requests
Log in to see full request history
TimeStatusUser Agent
Retrieving recent requests…
LoadingLoading…

The Validate Request API checks incoming traffic against DataDome's
bot detection engine. Your integration sends request metadata to DataDome, and we return a decision: allow or challenge.

DataDome API should be requested by a component of your backend infrastructure (CDN, load balancer, application server, etc).

🚧

Protection API (custom integration) is only available for Premium and Enterprise customer.

Pre-requisites to implement API Integration

External API Communication

  • The component must support synchronous HTTPS calls to external APIs.

HTTP Request Analysis

  • Ability to read and process all HTTP request headers.
  • Ability to access the end user’s IP address.
  • [Recommended] Ability to collect TLS JA3 and JA4 fingerprints from incoming requests.

Request Management

  • Configurable HTTP request timeout with a fail-open mechanism to maintain service continuity.
  • Ability to exclude static assets (e.g., .css, .js, .jpg, etc.) from DataDome processing.

Response Handling

  • Ability to dynamically inject custom headers into HTTP responses (e.g., Set-Cookie: datadome=xxxxxxxx).
  • Ability to store and forward data from the DataDome HTTP response to the final client response.
  • Ability to return custom HTTP responses (html or json) with specific status codes (e.g., 401, 403, etc.) based on DataDome feedback.

Handling API response status code and body

The DataDome response is dynamic. It tells the integration what decision to enforce and how to update the request/response headers.

1. Integrity Validation

Before processing the response, you must verify that the HTTP status code of the API response matches the value in the X-DataDomeResponse header.

  • If the values match: Proceed to the Response Logic below.
  • If the values do NOT match: Ignore the API response and allow the request to proceed to your application (Fail-open).

2. Response Logic

Once the response is validated, the module must behave based on the X-DataDomeResponse header returned:

ActionStatus CodesLogic to Follow
Allow200Pass the request
Forward the request (with mapped upstream headers) to your backend server.
Challenge301, 302, 401, 403, 429Challenge the request
Immediately return the DataDome API response (status code + body + mapped downstream headers) to the client. Do not contact your backend server.
Fail-openAll othersIgnore the error
Treat the request as allowed (200) to avoid blocking legitimate traffic due to system errors.

3. Handling API response headers

The DataDome API response contains instructions on how to modify both the upstream request (sent to your origin) and the downstream response (sent to the user). This must be done for both Allow and challenge status codes.

Universal Header Mapping

The API uses "Pointer Headers" to tell your module which specific headers to extract and where to move them. It is Mandatory for allow and challenge status codes.

Pointer HeaderPurposeAction Required
X-DataDome-request-headersUpstream MapLists headers in the API response that you must add to the request reaching your backend.
X-DataDome-headersDownstream MapLists headers in the API response that you must add to the response reaching the browser.

Security Guardrail: Never forward the "Pointer Headers" themselves (or any header listed inside them) back to the end-user. They are for your module's internal logic only.

Implementation Workflow

To process headers correctly, follow these two steps:

Step A: Update the Request (To Origin)

Check the value of X-DataDome-request-headers. It contains a space-separated list of header names. Extract these from the API response and inject them into the request before it hits your application. This feature is called Enriched headers

Step B: Update the Response (To User)

Check the value of X-DataDome-headers. Extract these from the API response and add them to the final response sent to the browser.

Practical Example

If the DataDome API response looks like this:

X-DataDome-request-headers: X-DataDome-isbot
X-DataDome-isbot: 1
X-DataDome-headers: Set-Cookie X-DD-B
Set-Cookie: datadome=ah78
X-DD-B: 1

The module's execution:

  • To your Application: Add the header X-DataDome-isbot: 1.
  • To the User: Add the headers Set-Cookie: datadome=ah78 and X-DD-B: 1.
  • Here is an example of response headers sent by the API:
X-DataDome-request-headers: X-DataDome-botname X-DataDome-botfamily X-DataDome-isbot
X-DataDome-botname: Crawler fake Google
X-DataDome-botfamily: bad_bot
X-DataDome-isbot: 1
X-DataDome-headers: Set-Cookie Pragma X-DataDome Cache-Control
Set-Cookie: datadome=some-value; Domain=domain.com; Path=/; Expires=Wed, 13 Jan 2021 22:23:01 GMT;
Pragma: no-cache
X-DataDome: protected
Cache-Control: no-cache
X-DataDomeResponse: 403

Functional requirements

Identifying the ClientID

The ClientIDis a mandatory field for the Protection API. It helps us to track the user session. Its source varies depending on whether the user is a standard web visitor or a client using Session by Header.

Extraction Logic

The module must check for the presence of the X-DataDome-ClientID header before falling back to the standard cookie.

Source PriorityLocationCondition
Priority 1X-DataDome-ClientID HeaderIf this header is present in the incoming request.
Priority 2datadome Cookie valueIf the custom header above is missing.
  • If an incoming HTTP request includes a X-DataDome-ClientID header, its value should be picked for the ClientID field instead of the datadome cookie.

Implementation Requirements

When you extract the ID from the Priority 1 (Header) source, you must also signal to DataDome that you are expecting a custom cookie response format:

  • Request Field: Map the extracted value to the ClientID field in your API payload.
  • Response Signal: You must add the header X-DataDome-X-Set-Cookie: true to the request sent to DataDome's Protection API.

Expected Result: DataDome will return the new cookie value in the X-Set-Cookie header instead of the standard Set-Cookie (You don't need to handle this case. It will be handled out of the box though headers management).

Implementation Example (Lua)

This logic ensures the correct ID is sent and the system knows how to handle the session update.

if request_headers['x-datadome-clientid'] ~= nil then  
   body['ClientID'] = request_headers['x-datadome-clientid']  
   datadomeHeaders["X-DataDome-X-Set-Cookie"] = "true"  
else  
   body['ClientID'] = clientId  
end

Sequential diagram of the full flow

Payload Formatting & Constraints

  • Encoding: All values must be URL encoded.
  • Header Handling: Exclude fields for empty headers.
  • Size & Truncation: To stay within the global 24 kB limit, truncate fields as listed below.
  • Reverse truncation : Fields with an asterisk (*) are truncated from the end.
FieldsLimit per field (in bytes)
Key, APIConnectionState, AuthorizationLen, CookiesLen, IP, Method, ModuleVersion, Port, PostParamLen, Protocol, RequestModuleName, TimeRequestUnlimited
JsonRpcVersion, SecCHDeviceMemory, SecCHUAMobile, SecFetchUser8
McpParamsClientInfoVersion, McpProtocolVersion, SecCHUAArch16
SecCHUAPlatform, SecFetchDest, SecFetchMode32
ContentType, JsonRpcRequestId, McpMethod, McpParamsClientInfoName, McpParamsToolName, McpSessionId, SecFetchSite64
AcceptCharset, AcceptEncoding, CacheControl, Connection, From, GraphQLOperationName, Pragma, SecCHUA, SecCHUAModel, TrueClientIP, UserID, X-Real-IP, X-Requested-With, ProductId128
AcceptLanguage, SecCHUAFullVersionList, Via256
Accept, ClientID, HeadersList, Host, Origin, ServerHostname, ServerName, Signature, SignatureAgent, XForwardedForIP*512
UserAgent768
CookiesList, Referer1024
Request, SignatureInput2048
Form Data
string
required
string
required
Defaults to text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
string
required
string
required
Defaults to gzip, deflate, sdch
string
required
Defaults to fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
string
Defaults to new
int32
required
string
required
string
required
string
Defaults to keep-alive
string
required
int32
required
string
required
float
int32
int32
string
string
string
string
required
int32
string
string
string
required
Defaults to Host,Connection,Pragma,Cookie,Cache-Control,User-Agent
string
required
Defaults to sub.domain.com
string
required
Defaults to 62.35.12.13
string
Defaults to e7d705a3286e19ea42f587b344ee6865
string
Defaults to t13d1516h2_8daaf6152771_02713d6af862
string
string
string
string
string
string
string
string
string
required
Defaults to GET
string
required
Defaults to 1.0
string
required
int32
required
Defaults to 60200
int32
required
string
required
Defaults to no-cache
string
string
required
Defaults to https
string
required
Defaults to http://sub.domain.com/home.php
string
required
Defaults to /folder/file.php?param=value
string
required
Defaults to my_connector
string
string
string
string
string
string
string
string
string
string
string
string
required
Defaults to sub.domain.com
string
required
Defaults to haproxy001
string
string
string
string
string
int64
required
Defaults to 1494584456492817
string
Defaults to 130113021303C02FC02BC030C02CCCA9CCA8C009C013C00AC014009C009D002F0035000A
string
Defaults to TLSv1.3
string
required
string
required
Defaults to Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.96 Safari/537.36
string
string
required
string
required
Defaults to 62.35.64.32,32.36.35.24
string
required
string
required
Headers
string
required
Defaults to application/x-www-form-urlencoded
Language
LoadingLoading…
Response
Click Try It! to start a request and see the response here!