CAPTCHA types · funcaptcha
FunCaptcha Solver API for Authorized Arkose Labs Testing
Use SolveHub's FunCaptcha solver API for authorized Arkose Labs QA. Review required challenge fields, proxy settings, live availability, result tokens and failures.
For authorized QA automation and browser integration. Use only on websites and workflows you have permission to test.
POST /v1/tasks with Authorization: Bearer <API_KEY>, Content-Type: application/json and an Idempotency-Key. Check availability in live prices first; see the quick start for the full create-and-poll flow.Availability notice: Arkose FunCaptcha changes its detection and challenges very frequently, so the solve rate may drop at any time and solving may be completely unavailable for short periods. Availability and success rate are not guaranteed for this type; do not rely on it for business that requires high availability. Failed tasks are not charged and the reserved amount is fully refunded; build retries and fallbacks into your integration.
Use SolveHub to create an Arkose Labs FunCaptcha task for a website and workflow you are authorized to test. A task requires a proxy, challengeInfo and browserInfo collected from the same real challenge. After the task completes, read the Arkose token from solution.solution.
FunCaptcha challenges and detection change frequently. Availability and success rates are not guaranteed, so check live status before creating a task and plan a fallback for tests that cannot wait. Failed tasks are not charged. Every value should come from your real page and browser; fabricated values are usually detected or fail outright.
FunCaptcha API at a Glance
- Required input: a proxy URL,
challengeInfoandbrowserInfo. - Create request:
POST /v1/taskswith typefuncaptchaand anIdempotency-Key. - Polling: save
taskIdand checkGET /v1/tasks/{taskId}about every 2–3 seconds. - Completed result: read the token from
solution.solution, notsolution.value. - Availability: check the current price and status before submitting; do not assume a task type is always available. See live prices.
Request fields
The outer type and task are required; the task.* paths below are inside the task object. Field names are case-sensitive. Length limits are measured in UTF-8 bytes.
| Field | Type | Required | Limit | Description |
|---|---|---|---|---|
type |
String | Yes | Fixed to funcaptcha |
Platform task type. |
task |
JSON object | Yes | ≤ 7 MiB | Task parameters for this type. |
task.proxy |
Proxy URL with port | Yes | ≤ 2048 bytes | Proxy used while solving, as protocol://user:pass@host:port or protocol://ip:port; protocol is http, https, or socks5; port 1–65535. |
task.challengeInfo |
Object | Yes | See table below | Captcha and fingerprint configuration. |
task.browserInfo |
Object | Yes | See table below | Browser impersonation settings. |
challengeInfo fields
41 fields, 12 of them required. Omit an optional field to use the default behavior; when sent it must have the listed type, otherwise the create request returns 400 INVALID_TASK. Fields not listed are rejected.
| Field | Type | Required | Description |
|---|---|---|---|
challengeInfo.publicKey |
Non-empty string | Yes | The site's Arkose public key (the data-pkey / public_key value on the page). |
challengeInfo.site |
Non-empty string | Yes | The site where the captcha appears. |
challengeInfo.surl |
Non-empty string | Yes | The site's Arkose service URL, e.g. https://xxx.arkoselabs.com. |
challengeInfo.apiUrl |
Non-empty string | No | Full URL of the captcha api.js. |
challengeInfo.capiMode |
Non-empty string | Yes | Captcha mode, e.g. lightbox, inline. |
challengeInfo.styleTheme |
Non-empty string | Yes | Captcha style theme, usually default. |
challengeInfo.locationHref |
Non-empty string | Yes | location.href of the page (iframe) hosting the captcha. |
challengeInfo.documentReferrer |
Non-empty string | Yes | document.referrer of that page. |
challengeInfo.documentTitle |
Non-empty string | No | document.title of that page. |
challengeInfo.iframeUrl |
Non-empty string | No | URL of the captcha iframe. |
challengeInfo.ancestorOrigins |
String array | Yes | The location.ancestorOrigins list; may be empty. |
challengeInfo.treeIndex |
Integer array | Yes | Position of the frame in the page's frame tree, e.g. [0]; may be empty. |
challengeInfo.treeStructure |
Non-empty string | Yes | Frame tree structure string, e.g. "[[]]". |
challengeInfo.languageEnabled |
Boolean | Yes | Whether a custom language is enabled. |
challengeInfo.jsfEnabled |
Boolean | Yes | Whether JavaScript fonts are enabled. |
challengeInfo.appMode |
Boolean | No | Set true when the captcha runs inside an app rather than a browser. |
challengeInfo.uniqueFingerprint |
Boolean | No | Use a brand-new fingerprint every time instead of the default algorithm. |
challengeInfo.oldFingerprint |
Boolean | No | Use an older fingerprint for more randomness. |
challengeInfo.overrideFingerprint |
Boolean | No | Override the fingerprint's Sec-Ch-Ua and User-Agent with the values you send. |
challengeInfo.syntheticFingerprint |
Boolean | No | Merge synthetic data into the fingerprint. |
challengeInfo.randomProtoChain |
Boolean | No | Use a random prototype-chain hash. |
challengeInfo.randomVideoExtended |
Boolean | No | Use random extended video codecs. |
challengeInfo.staticSpeechData |
Boolean | No | Use the default speech voice data. |
challengeInfo.customTimezoneOffset |
Integer | No | Timezone offset in minutes, same as JavaScript getTimezoneOffset(). |
challengeInfo.historyLength |
Integer | No | Browsing history length to include (history.length). |
challengeInfo.noIframe |
Boolean | No | Set true when the captcha is not loaded through a separate iframe. |
challengeInfo.lowBandwidthMode |
Boolean | No | Low-bandwidth mode: use the latest capi info and send fewer optional requests; may be detected or use wrong capi info. |
challengeInfo.storageAccess |
Boolean | No | Whether the Sec-Fetch-Storage-Access header is used. |
challengeInfo.solvePOW |
Boolean | No | Solve the proof-of-work (PoW) challenge when one is given. |
challengeInfo.cookieTimestamp |
Boolean | No | Whether to include the timestamp cookie. |
challengeInfo.disableArid |
Boolean | No | Disable the ARID cookie and the X-Ark-Arid header. |
challengeInfo.disableAridCookie |
Boolean | No | Disable only the ARID cookie. |
challengeInfo.disableCookies |
Boolean | No | Disable all cookies. |
challengeInfo.disableCookiesAnalytics |
Boolean | No | Disable analytics cookies. |
challengeInfo.disableGT2Cookies |
Boolean | No | Disable cookies for the gt2/public_key endpoint. |
challengeInfo.disableNavigatorCookies |
Boolean | No | Disable navigator cookies (navigator.cookieEnabled). |
challengeInfo.powPause |
Boolean | No | Add a realistic pause emulating the CPU solving the proof-of-work. |
challengeInfo.exploitMode |
Boolean | No | Use a faster exploit-based solve without a proxy. |
challengeInfo.skipHighWaves |
Boolean | No | Give up with an error instead of solving challenges with 6 or more waves. |
challengeInfo.submitAnswerPause |
Boolean | No | Add a realistic pause when submitting answers. |
challengeInfo.extraData |
Object | No | Extra data sent to FunCaptcha as data[<key>], e.g. Roblox's {"blob": "..."}. |
browserInfo fields
16 fields, 5 of them required (User-Agent, Linux, Mac, Mobile, Safari). User-Agent, Sec-Ch-Ua, Accept-Language, etc. should come from the same real browser and match the platform flags.
| Field | Type | Required | Description |
|---|---|---|---|
browserInfo.Accept-Language |
Non-empty string | No | The Accept-Language header, e.g. en-US,en;q=0.9. |
browserInfo.Cache |
Boolean | No | Whether to use the browser cache. |
browserInfo.Cookie |
Non-empty string | No | Cookie to use while solving. |
browserInfo.DNT |
Boolean | No | Whether to add the Do Not Track header (good for browsers like Brave). |
browserInfo.HTTP3 |
Boolean | No | Whether to use the HTTP/3 protocol; your proxy must support it. |
browserInfo.Linux |
Boolean | Yes | Whether to impersonate a Linux device. |
browserInfo.Mac |
Boolean | Yes | Whether to impersonate a Mac device. |
browserInfo.Mobile |
Boolean | Yes | Whether to impersonate a mobile device. |
browserInfo.Safari |
Boolean | Yes | Whether to impersonate the Safari browser. |
browserInfo.Sec-Ch-Ua |
Non-empty string | No | The Sec-Ch-Ua header. |
browserInfo.Sec-Ch-Ua-Platform |
Non-empty string | No | The Sec-Ch-Ua-Platform header, e.g. "Windows". |
browserInfo.User-Agent |
Non-empty string | Yes | The User-Agent header; keep it consistent with Linux/Mac/Mobile/Safari. |
browserInfo.dataBrands |
Non-empty string | No | Data brands used in the fingerprint. |
browserInfo.languages |
Non-empty string | No | Languages to use; should generally match Accept-Language. |
browserInfo.randomTLS |
Boolean | No | Use a random TLS fingerprint; this breaks HTTP/3. |
browserInfo.userbrowser |
Non-empty string | No | The userbrowser value, which can differ slightly from User-Agent. |
Create request example
The example below contains only the required fields and common headers. All values are placeholders and must be replaced with real values from your page.
{
"type": "funcaptcha",
"task": {
"proxy": "http://user:pass@203.0.113.10:8080",
"challengeInfo": {
"publicKey": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"site": "https://example.com",
"surl": "https://example.arkoselabs.com",
"capiMode": "lightbox",
"styleTheme": "default",
"locationHref": "https://example.com",
"documentReferrer": "https://example.com",
"ancestorOrigins": [
"https://example.com"
],
"treeIndex": [
0
],
"treeStructure": "[[]]",
"languageEnabled": true,
"jsfEnabled": true
},
"browserInfo": {
"Accept-Language": "en-US,en;q=0.9",
"Linux": false,
"Mac": false,
"Mobile": false,
"Safari": false,
"Sec-Ch-Ua": "\"Chromium\";v=\"152\", \"Not?A_Brand\";v=\"24\", \"Google Chrome\";v=\"152\"",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/152.0.0.0 Safari/537.36"
}
}
}
cURL call
Replace the key, site details, and proxy in the example with your actual values; keep the Idempotency-Key unchanged for the same business request.
curl -sS -X POST 'https://www.tiam.codes/v1/tasks' \
-H 'Authorization: Bearer sh_REPLACE_ME' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: example-funcaptcha-0001' \
--data-binary @- <<'JSON'
{
"type": "funcaptcha",
"task": {
"proxy": "http://user:pass@203.0.113.10:8080",
"challengeInfo": {
"publicKey": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"site": "https://example.com",
"surl": "https://example.arkoselabs.com",
"capiMode": "lightbox",
"styleTheme": "default",
"locationHref": "https://example.com",
"documentReferrer": "https://example.com",
"ancestorOrigins": [
"https://example.com"
],
"treeIndex": [
0
],
"treeStructure": "[[]]",
"languageEnabled": true,
"jsfEnabled": true
},
"browserInfo": {
"Accept-Language": "en-US,en;q=0.9",
"Linux": false,
"Mac": false,
"Mobile": false,
"Safari": false,
"Sec-Ch-Ua": "\"Chromium\";v=\"152\", \"Not?A_Brand\";v=\"24\", \"Google Chrome\";v=\"152\"",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/152.0.0.0 Safari/537.36"
}
}
}
JSON
Create response and polling
A successful create returns HTTP 202, and status is usually queued at first. Save the taskId and call GET /v1/tasks/{taskId} about every 2–3 seconds. The soft time limit for this type is 180 seconds. While solving, the status is dispatching or processing; when finished it is completed or failed. A task that still has no result after the time limit becomes uncertain; keep polling the original task and do not recreate it with a new idempotency key.
Result fields
When status=completed, solution is an object:
| Field | Type | How to read |
|---|---|---|
solution.solution |
String | The Arkose token to submit to the target site (usually as fc-token / verification-token). A ` |
solution.gameInfo.gameType |
Integer | Game type of this challenge. |
solution.gameInfo.variant |
String | Challenge variant; silent_pass means it passed without answering. |
solution.gameInfo.waves |
Integer | Number of answered waves; 0 means a silent pass. |
solution.gameInfo.solveTime |
Number | Solve time in seconds. |
Successful response example:
{
"taskId": "5a1c6c55-7f3b-4c5d-9a7e-2f0d8e1b9c21",
"type": "funcaptcha",
"status": "completed",
"priceMicros": 2000,
"traceId": "0f3b2d7e-91a4-4c62-8a51-7d2e9c4b1f08",
"solution": {
"gameInfo": {
"gameType": 4,
"solveTime": 0.32,
"variant": "silent_pass",
"waves": 0
},
"solution": "XXXXXXXXXXXXXXXXX.XXXXXXXXXX|r=eu-west-1|meta=3|metabgclr=transparent|metaiconclr=%23757575|maintxtclr=%23b8b8b8|guitextcolor=%23474747|pk=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX|at=40|sup=1|rid=1|ag=101|cdn_url=https%3A%2F%2Fexample.arkoselabs.com%2Fcdn%2Ffc|surl=https%3A%2F%2Fexample.arkoselabs.com|smurl=https%3A%2F%2Fexample.arkoselabs.com%2Fcdn%2Ffc%2Fassets%2Fstyle-manager"
},
"createdAt": "2026-10-13T08:00:00Z",
"finishedAt": "2026-10-13T08:00:06Z"
}
Failed response example:
{
"taskId": "5a1c6c55-7f3b-4c5d-9a7e-2f0d8e1b9c21",
"type": "funcaptcha",
"status": "failed",
"priceMicros": 2000,
"traceId": "0f3b2d7e-91a4-4c62-8a51-7d2e9c4b1f08",
"errorCode": "TASK_FAILED",
"failureReason": "Too many waves to solve, make skipHighWaves false in challengeInfo to solve anyway",
"createdAt": "2026-10-13T08:00:00Z",
"finishedAt": "2026-10-13T08:00:04Z"
}
Failures and troubleshooting
A failed task (status=failed) is not charged and the reserved amount is fully refunded; failureReason gives the specific reason returned by the solving service. Common reasons and fixes:
| failureReason (example) | Cause | What to do |
|---|---|---|
Too many waves to solve, make skipHighWaves false in challengeInfo to solve anyway |
The challenge has 6 or more waves and challengeInfo.skipHighWaves is true. |
Set skipHighWaves to false (or omit it) and create a new task. |
Failed to get proxy / IP information |
The proxy cannot be reached or its exit IP cannot be determined. | Check the proxy address, port, credentials, and availability. |
Incorrect proxy format. Please use protocol://user:pass@host:port or protocol://ip:port |
The solving service does not accept the proxy format. | Use protocol://user:pass@host:port. |
HTTP/3 proxies must be used on Roblox right now |
The solving service currently requires HTTP/3 proxies for Roblox, and the proxy does not qualify. | Switch to a proxy that supports HTTP/3 and retry. |
Unsupported surl |
This surl is not supported yet. |
Make sure the surl comes from the real page; if it is still unsupported, contact platform support. |
Use a new Idempotency-Key when resubmitting (the same key returns the original failed task). If a field type or required field is invalid, the create request returns 400 INVALID_TASK directly, with no task and no charge.
Common create-request errors are 400 INVALID_TASK, 402 INSUFFICIENT_BALANCE, 429 TASK_LIMIT_EXCEEDED, and 503 TYPE_UNAVAILABLE. When a created task fails, the public error code is TASK_FAILED or TASK_TIMEOUT; uncertain maps to TASK_UNCERTAIN. See the Platform API Reference for details.
Related documentation
Last updated: