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. When Castle determines that a request may be automated, it presents a verification challenge. The uCaptcha API solves Castle challenges and returns a verification token, with or without a proxy.

TypeProxyDescription
CastleTokenProxyLessNoSolve without proxy (recommended)
CastleTokenYesSolve using your proxy
ParameterTypeRequiredDescription
typestringYesTask type from the table above
websiteURLstringYesURL of the page with the Castle challenge
websiteKeystringYesCastle site key (publishable API key)

Required when using the CastleToken task type.

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"
}
}
{
"errorId": 0,
"taskId": "abc-123-def"
}
{
"token": "castle_request_token_eyJhbGciOi...verification"
}
FieldTypeDescription
tokenstringThe Castle verification token to submit with the request

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.
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"
}
})
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"
}
})
}).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"
}
}'
# 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