> For the complete documentation index, see [llms.txt](https://docs.apexsolutions.lol/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apexsolutions.lol/cloudflare-js-d/workflow.md).

# Integration Workflow

The end-to-end Cloudflare JS-D integration: confirm the challenge, solve it, and replay the clearance.

The step-by-step implementation of the Cloudflare JS-D flow. Each step describes what to do and why, with the actual requests against Apex. The full request and response reference lives in the **API reference**.

## Step 1: Confirm the challenge

GET the protected page with your Chrome TLS client. If it is behind JS-D, the HTML carries the inline `__CF$cv$params` block:

```html
<script>
  window.__CF$cv$params = { r: "{r}", t: "{t}" };
  ...
</script>
```

A quick check over the HTML is enough to confirm the right provider:

```python
import re

html = open("page.html").read()

if "__CF$cv$params" in html and "challenge-platform/scripts/jsd/main.js" in html:
    print("JS-D present")
elif "window._cf_chl_opt" in html:
    print("Managed/Turnstile challenge - not JS-D")
else:
    print("no JS-D challenge found")
```

You do not need the `r`/`t` values for the solve — Apex extracts them. Confirming JS-D is present tells you the provider to call.

## Step 2: Build the solve

Call Apex with the target URL, `challenge: "jsd"`, your sticky proxy, and your real Chrome-on-Windows User-Agent. The `user_agent` is required — the fingerprint and the request headers derive from it:

{% tabs %}
{% tab title="Go" %}

```go
package main

import (
	"bytes"
	"encoding/json"
	"net/http"
)

func main() {
	body, _ := json.Marshal(map[string]any{
		"params": map[string]any{
			"url":        "https://{target}",
			"challenge":  "jsd",
			"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/150.0.0.0 Safari/537.36",
		},
		"proxy": "http://user:pass@host:port",
	})

	req, _ := http.NewRequest("POST", "https://jsd.apexsolutions.lol/payload", bytes.NewReader(body))
	req.Header.Set("Authorization", "Bearer your-api-key")
	req.Header.Set("Content-Type", "application/json")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
}
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

resp = requests.post(
    "https://jsd.apexsolutions.lol/payload",
    headers={"Authorization": "Bearer your-api-key"},
    json={
        "params": {
            "url": "https://{target}",
            "challenge": "jsd",
            "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/150.0.0.0 Safari/537.36",
        },
        "proxy": "http://user:pass@host:port",
    },
)

print(resp.status_code, resp.json())
```

{% endtab %}

{% tab title="JS/TS" %}

```jsts
const resp = await fetch("https://jsd.apexsolutions.lol/payload", {
  method: "POST",
  headers: {
    "Authorization": "Bearer your-api-key",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    params: {
      url: "https://{target}",
      challenge: "jsd",
      user_agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/150.0.0.0 Safari/537.36",
    },
    proxy: "http://user:pass@host:port",
  }),
});

const data = await resp.json();
console.log(data);
```

{% endtab %}
{% endtabs %}

The response gives you the clearance under `result` — `cf_clearance` plus any extra cookies Cloudflare set during the solve (`__cf_bm`). The full response is documented in the API reference.

## Step 3: Replay the clearance

Attach the returned cookies to your requests — with the same User-Agent and the same proxy that obtained them:

```python
import requests

s = requests.Session()
s.proxies = {"http": "http://user:pass@host:port", "https": "http://user:pass@host:port"}
s.headers["User-Agent"] = result["result"]["user_agent"]

for name, value in result["result"]["cookies"]:
    s.cookies.set(name, value)

s.get("https://{target}/protected")
```

If the site answers with a fresh challenge, the clearance was rejected — check that you are using the same proxy and TLS profile end to end.

## Important Notes

{% hint style="info" %}
**Consistency is everything.** `cf_clearance` only validates when replayed with the same User-Agent and IP that obtained it. JS-D has no follow-up requests — there is no session id and no flush endpoint. A `proxy` is always required, and the `user_agent` must be Google Chrome on Windows.
{% endhint %}
