DataDome cookie: Best practices on iOS

Do's and don'ts

What is the DataDome cookie

The DataDome cookie is used to keep information about the end user's session. It keeps information about whether or not the end user has passed a DataDome CAPTCHA or if the device has been verified by Device Check.

Losing this cookie means loosing all information about the current session, and this can lead to more DataDome CAPTCHA or Device Check.

In some cases, losing the cookie can lead to what we call a challenge loop, displaying challenges after challenges, blocking the user from continuing using your application.

Our iOS SDKs are responsible for managing the DataDome cookie and it is stored inside the shared HTTPCookieStorage. That way, we ensure that the DataDome cookie is always passed to requests to the same domain.

What to do with the DataDome cookie

The SDKs are doing most of the work, so you normally don't have to manipulate the DataDome cookie.

The only exception is when switching from an application context to a WebView context. In that case, follow the instructions from the general SDK documentation.

What NOT to do with the DataDome cookie

Do not disable the HTTPCookieStorage

The DataDome cookie is stored inside the shared HTTPCookieStorage. Because of that, disabling the HTTPCookieStorage for your URLSession or for a request will lead to a cookie loss.

Here are a few example of things to avoid doing:

var request = URLRequest(url: testUrl)
request.httpShouldHandleCookies = false // the DataDome cookie will be lost
let configuration = URLSessionConfiguration.ephemeral // This configuration will not use the HTTPCookieStorage
let session = URLSession(configuration: configuration)
let configuration = URLSessionConfiguration.default

configuration.httpCookieStorage = nil // No HTTPCokieStorage means no DataDome cookie in your requests
// OR
configuration.httpCookieStorage = HTTPCookieStorage() // Only the HTTPCookieStorage.shared should be used
// OR
configuration.httpShouldSetCookies = false // Requests emitted by this session won't contain cookies from the HTTPCookieStorage
// OR
configuration.httpCookieAcceptPolicy = .never

let session = URLSession(configuration: configuration)

Do not add a Cookie header to your request manually

When some of your request requires to be sent with a specific cookie, it may be tempting to add the cookie in this way…

request.addValue("myCookie=something", forHTTPHeaderField: "Cookie")
// OR
request.setValue("myCookie=something", forHTTPHeaderField: "Cookie")

…but this will cause a bypass of the HTTPCookieStorage, leading to a DataDome cookie loss for this request.

When possible, it is better to add your own cookies to the shared HTTPCookieStorage, like this:

let cookie = HTTPCookie(properties: [.name: "myCookie",
                                     .value: "cookieValue",
                                     .path: "/",
                                     .domain: ".yourDomain.com"])
HTTPCookieStorage.shared.setCookie(cookie)

This will ensure that your cookies and all other cookies with a matching domain, including the DataDome cookie, are added to the request.

There may be some cases where you absolutely don't want to add your cookies to the HTTPCookieStorage. In this case, you will need to build the Cookie header properly by including all of the cookies that should have been added by the HTTPCookieStorage

let cookies = HTTPCookieStorage.shared.cookies(for: url) ?? []
let headerFields = HTTPCookie.requestHeaderFields(with: cookies)
request.setValue(headerFields["Cookie"] , forHTTPHeaderField: "Cookie")
            
request.addValue("myCookie=azerty", forHTTPHeaderField: "Cookie")