Skip to content

Castle

Castle is a bot detection and account security platform that uses device fingerprinting, behavioral analysis, and risk scoring to protect web applications from automated threats. Castle solving is primarily browser-fingerprint based and usually does not require solving through the same IP used for the final protected request. The target service validates IP/session context when you submit the solved Castle token.

TypeProxyDescription
CastleTokenProxyLessNoSolve without proxy (recommended)
CastleTokenOptionalAccepts proxy fields for compatibility, but Castle solving usually does not require a proxy
ParameterTypeRequiredDescription
typestringYesTask type from the table above
websiteURLstringYesURL of the page with the Castle challenge
websiteKeystringYesCastle site key (publishable API key)
metadata.wUrlstringRecommendedCastle worker script URL (cw.js) used by CapMonster
metadata.swUrlstringRecommendedCastle service worker script URL (csw.js) used by CapMonster
metadata.countintegerNoNumber of Castle request tokens to generate when supported
config_jsonobjectNoRiskByPass-native Castle config. If omitted, uCaptcha derives it from websiteKey and metadata when routing to RiskByPass

Optional for Castle. If provided, proxy fields are forwarded to providers that accept them, but the important IP check normally happens when your client submits the solved token to the protected endpoint.

ParameterTypeRequiredDescription
proxyTypestringYeshttp, socks4, or socks5
proxyAddressstringYesProxy IP or hostname
proxyPortintegerYesProxy port
proxyLoginstringNoProxy username
proxyPasswordstringNoProxy password
{
"clientKey": "YOUR_API_KEY",
"task": {
"type": "CastleTokenProxyLess",
"websiteURL": "https://example.com/login",
"websiteKey": "pk_abc123def456ghi789",
"metadata": {
"wUrl": "https://example.com/path/to/cw.js",
"swUrl": "https://example.com/path/to/csw.js",
"count": 1
}
}
}
{
"errorId": 0,
"taskId": "abc-123-def"
}
{
"token": "castle_request_token_eyJhbGciOi...verification",
"xCastleRequestToken": "castle_request_token_eyJhbGciOi...verification",
"x-castle-request": "castle_request_token_eyJhbGciOi...verification",
"x-castle-request-token": "castle_request_token_eyJhbGciOi...verification",
"tokens": ["castle_request_token_eyJhbGciOi...verification"],
"__cuid": "castle_cuid_cookie_value",
"cookie": "__cuid=castle_cuid_cookie_value",
"cookies": {
"__cuid": "castle_cuid_cookie_value"
}
}
FieldTypeDescription
tokenstringFirst Castle request token returned by the provider
xCastleRequestTokenstringCamel-case alias for token
x-castle-requeststringHeader-friendly alias for token
x-castle-request-tokenstringHeader-friendly alias for token
tokensstring[]All Castle request tokens returned by the provider
__cuidstringCastle __cuid cookie value when returned by the provider
cookiestringReady-to-use cookie header fragment for __cuid
cookiesobjectCookie map, including __cuid when available

Once you receive the token value from the solution:

  1. Request header — Include the Castle token in the X-Castle-Request-Token header when making requests to the protected endpoint.
  2. JavaScript injection — Set the token in Castle’s client-side SDK before the form is submitted.
  3. Cookie — If the solution includes __cuid, send it with the same request/session when the protected integration expects Castle cookies.
  4. Submission context — Submit the token from the browser/client IP and session that the protected service expects. Castle’s IP validation generally happens at this submission step, not during solving.
import requests
import time
API_KEY = "YOUR_API_KEY"
# Create task
response = requests.post("https://api.ucaptcha.net/createTask", json={
"clientKey": API_KEY,
"task": {
"type": "CastleTokenProxyLess",
"websiteURL": "https://example.com/login",
"websiteKey": "pk_abc123def456ghi789",
"metadata": {
"wUrl": "https://example.com/path/to/cw.js",
"swUrl": "https://example.com/path/to/csw.js",
"count": 1
}
}
})
task_id = response.json()["taskId"]
# Poll for result
while True:
result = requests.post("https://api.ucaptcha.net/getTaskResult", json={
"clientKey": API_KEY,
"taskId": task_id
}).json()
if result["status"] == "ready":
token = result["solution"]["token"]
print("Token:", token)
break
elif result["status"] == "failed":
print("Error:", result.get("errorDescription"))
break
time.sleep(5)
const API_KEY = "YOUR_API_KEY";
const { taskId } = await fetch("https://api.ucaptcha.net/createTask", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
clientKey: API_KEY,
task: {
type: "CastleTokenProxyLess",
websiteURL: "https://example.com/login",
websiteKey: "pk_abc123def456ghi789",
metadata: {
wUrl: "https://example.com/path/to/cw.js",
swUrl: "https://example.com/path/to/csw.js",
count: 1
}
}
})
}).then(r => r.json());
while (true) {
const result = await fetch("https://api.ucaptcha.net/getTaskResult", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ clientKey: API_KEY, taskId })
}).then(r => r.json());
if (result.status === "ready") {
console.log("Token:", result.solution.token);
break;
} else if (result.status === "failed") {
console.error("Error:", result.errorDescription);
break;
}
await new Promise(r => setTimeout(r, 5000));
}
Terminal window
# Create task
curl -X POST https://api.ucaptcha.net/createTask \
-H "Content-Type: application/json" \
-d '{
"clientKey": "YOUR_API_KEY",
"task": {
"type": "CastleTokenProxyLess",
"websiteURL": "https://example.com/login",
"websiteKey": "pk_abc123def456ghi789",
"metadata": {
"wUrl": "https://example.com/path/to/cw.js",
"swUrl": "https://example.com/path/to/csw.js",
"count": 1
}
}
}'
# Poll for result (replace TASK_ID with the taskId from above)
curl -X POST https://api.ucaptcha.net/getTaskResult \
-H "Content-Type: application/json" \
-d '{
"clientKey": "YOUR_API_KEY",
"taskId": "TASK_ID"
}'
  • CapMonster
  • RiskByPass

The following legacy type names are also accepted for backward compatibility:

  • CastleTask
  • CastleTaskProxyless
  • CustomTask:Castle