# Slider CAPTCHA

## Datadome Captcha Workflow

This workflow guides you through solving **Datadome captcha challenges** using our API. Captcha blocks are typically encountered on high-security endpoints and require strict browser emulation.

> ⚠️ **Before proceeding:**\
> Ensure you are using a **Chrome TLS client**, and your requests **perfectly match** Chrome browser behavior. Any deviations — in headers, TLS fingerprint, or request flow — may invalidate the resulting `datadome` cookie.

***

### 🧱 Step 1: Detect a Captcha Block

Send a **GET request** to a protected page. If you’re blocked by a captcha, the HTML response will include:

* A script reference to `https://ct.captcha-delivery.com/c.js`
* A `<script>` element with a JavaScript object like this:

```html
<script>
  var dd = {
    'rt': 'c',
    'cid': 'AHrlqAAAAAMASuDzOQlFQzIALvhm3g==',
    'hsh': 'EC3B9FB6F2A31D3AF16C270E6531D2',
    't': 'fe',
    's': 43337,
    'e': '16fbe80bb40a1dfb31c417e8849d8d22...',
    'host': 'geo.captcha-delivery.com'
  };
</script>
```

***

### 🔗 Step 2: Construct the Captcha Link

Using the `dd` object, build a captcha URL with the following query parameters:

* `initialCid`
* `hash`
* `cid` (your session/client identifier)
* `t`
* `referer` (URL-encoded original page)
* `s`
* `e`
* `dm`

#### Example URL:

<pre class="language-html"><code class="lang-html"><strong>https://geo.captcha-delivery.com/captcha/?
</strong>initialCid=AHrlqAAAAAMASuDzOQlFQzIALvhm3g%3d%3d
&#x26;hash=&#x3C;datadome_site_key>
&#x26;cid=&#x3C;initial_datadome_cookie>
&#x26;t=fe
&#x26;referer=&#x3C;referer>
&#x26;s=&#x3C;s_value_from_dd_json>
&#x26;e=&#x3C;e_value_from_dd_json>
&#x26;dm=cd
</code></pre>

> 🛑 If the value of `t` is `bv`, your proxy is banned. **Rotate your proxy** and retry the request until you receive a `t=fe` response.

Also, **remove any old `datadome` cookies** before retrying or you may get stuck in a loop.

Here is a Golang implementation for constructing the CAPTCHA link:

```go
type DDCaptcha struct {
	Rt   string `json:"rt"`
	Cid  string `json:"cid"`
	Hash string `json:"hsh"`
	T    string `json:"t"`
	S    int64  `json:"s"`
	E    string `json:"e"`
	Host string `json:"host"`
}

func parseSliderCaptcha(body []byte) (map[string]interface{}, error) {
	re := regexp.MustCompile(`(?s)sliderCaptcha\((.*?)\)`)

	matches := re.FindSubmatch(body)

	if len(matches) > 1 {
		ddJson := string(matches[1])
		ddJson = strings.Replace(ddJson, "'", "\"", -1)

		keyPattern := regexp.MustCompile(`(?m)^\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*:`)
		jsonContent := keyPattern.ReplaceAllString(ddJson, `"$1":`)

		var dd map[string]interface{}
		if err := json.Unmarshal([]byte(jsonContent), &dd); err != nil {
			return nil, fmt.Errorf("error parsing JSON: %v", err)
		}
		return dd, nil
	}
	return nil, fmt.Errorf("unable to parse sliderCaptcha JSON")
}

func buildCaptchaLink(initialCookie, referer string, ddObject *DDCaptcha) (string, error) {
	initialCid := ddObject.Cid
	referer = url.QueryEscape(referer)
	s := ddObject.S
	e := ddObject.E
	t := ddObject.T
	siteKey := ddObject.Hash

	baseURL := "https://geo.captcha-delivery.com/captcha/"

	params := []struct {
		key, value string
	}{
		{"initialCid", url.QueryEscape(initialCid)},
		{"hash", siteKey},
		{"cid", initialCookie},
		{"t", t},
		{"referer", referer},
		{"s", strconv.FormatInt(s, 10)},
		{"e", e},
		{"dm", "cd"},
	}

	var queryParts []string
	for _, param := range params {
		queryParts = append(queryParts, param.key+"="+param.value)
	}

	finalURL := baseURL + "?" + strings.Join(queryParts, "&")

	return finalURL, nil
}
```

***

### 🖼️ Step 3: Retrieve Captcha Images

Make a **GET request** to the captcha link.

Ensure the HTML response contains:

* `var captcha = sliderCaptcha({...})`
* The Datadome comment: `/** DataDome is a cybersecurity solution...`

#### Extract Image Paths:

1. Parse the `captchaChallengePath` value to get the **main background image** (ends in `.jpg`)
2. Replace `.jpg` with `.frag.png` to get the **fragment (slider) image**

Download both images and **base64-encode** the raw binary data of each.

Here is a Golang implementation to parse the `captchaObject` to get the image/fragment paths:

```go
func parseSliderCaptcha(body []byte) (map[string]interface{}, error) {
	re := regexp.MustCompile(`(?s)sliderCaptcha\((.*?)\)`)

	matches := re.FindSubmatch(body)

	if len(matches) > 1 {
		ddJson := string(matches[1])
		ddJson = strings.Replace(ddJson, "'", "\"", -1)

		keyPattern := regexp.MustCompile(`(?m)^\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*:`)
		jsonContent := keyPattern.ReplaceAllString(ddJson, `"$1":`)

		var dd map[string]interface{}
		if err := json.Unmarshal([]byte(jsonContent), &dd); err != nil {
			return nil, fmt.Errorf("error parsing JSON: %v", err)
		}
		return dd, nil
	}
	return nil, fmt.Errorf("unable to parse sliderCaptcha JSON")
}

captchaObject, err := parseSliderCaptcha(captchaPage) 
if err != nil { 	
	return nil, errors.New("unable to parse slider captcha parameters")
} 
backgroundImageUrl := captchaObject["captchaChallengePath"].(string)
fragmentImageUrl := strings.TrimSuffix(backgroundImageUrl, ".jpg") + ".frag.png"

```

***

### 🔧 Step 4: Solve Using Our API

See [API Reference](https://api-docs.yoghurtbot.net/api-reference#post-captcha)

The response will contain a `captchaSubmitUrl` field. This is the fully constructed URL for submitting the solution.

***

### 📤 Step 5: Submit Captcha Solution

Make a **GET request** to the `captchaSubmitUrl` returned by our API.

Ensure that your headers **match Chrome browser behavior exactly**, especially:

* `user-agent`
* `sec-ch-ua` and related client hints
* `referer` matching the captcha page
* Proper header ordering

***

### 🍪 Step 6: Handle the Response

If the captcha is accepted, the response will include:

```json
{
  "cookie": "datadome=...; Max-Age=31536000; Domain=.example.com; Path=/; Secure; SameSite=Lax"
}
```

Extract and store this `datadome` cookie in your cookie jar for future requests to the target domain.

***

### 🔁 Step 7: Retry Original Request

Retry the original request **using the solve cookie**.

* If it works: 🎉 You’re in!
* If still blocked:
  * Retry up to **3 times**
  * If unsuccessful, **rotate your proxy**
  * **Clear any old cookies** and restart the entire workflow from Step 1
