Was this helpful?
How to Bypass Funcaptcha
Technical engineer
Introduction
Funcaptcha (Arkose Labs) is one of the most temperamental captchas out there: interactive challenges, dynamic generation, constant security updates. We've noticed that when parsers start throwing ERROR_CAPTCHA_UNSOLVABLE, 80% of the time it's not the code—it's three things: stale blob, wrong userAgent, or missing reports.
Let's walk through setting up communication with 2Captcha so captchas solve reliably and your balance doesn't drain on retry attempts.
Step 1. What You Need
Five parameters are critical. If even one is off—your task goes to UNSOLVABLE.
| Parameter | Why | Where to Get |
|---|---|---|
| websitePublicKey | Captcha identifier on the site | Page source or requests to arkoselabs.com |
| websiteURL | Page address | Browser address bar |
| userAgent | Browser string to imitate session | navigator.userAgent in DevTools console |
| data[blob] | Temporary session token | See Step 2 |
| proxy | IP address for session binding | Your proxy server (see Step 3) |
Step 2. How to Get data[blob]
Blob lives 1–5 minutes and is single-use. Without it or with an expired one—error is guaranteed.
Via Network (more reliable)
- DevTools (F12) → Network tab
- Filter: fc|arkose|enforcement
- Find request enforcement.abc123... or fc/api
- In Preview find "blob"
json
"blob": "B7A24B7D-15EF-41...D3F5"
Via Console
javascript
console.log(
document.querySelector('iframe[src*="arkoselabs"]')
.contentWindow.document.body.innerHTML
.match(/"blob":"([^"]+)"/)[1]
);
Important: Don't reuse blob—Arkose detects this.
Step 3. Proxy Setup
Arkose Labs strictly checks IP reputation. Data centers often get blocked immediately, so residential proxies are critical for Funcaptcha.
API Format: separate fields (see Step 4)
Rules:
- Proxy geo must match websiteURL (if site is US—use US proxy).
- userAgent and proxy must belong to the same session (don't mix Chrome/WIN with a proxy used for Firefox/LINUX).
- For mass tasks, rotate proxies, but don't change them mid-captcha session.
No proxy? 2Captcha provides access to a pool of residential proxies optimized for captcha solving. Connect them in your dashboard.
Step 4. Submitting the Task (API v2)
We work with JSON format only. It's more stable, returns structured errors, and supports extended parameters.
Create Task
Endpoint: POST https://api.2captcha.com/createTask
json
{
"clientKey": "YOUR_API_KEY",
"task": {
"type": "FunCaptchaTask",
"websiteURL": "https://target-site.com/page",
"websitePublicKey": "YOUR_PUBLIC_KEY",
"proxyType": "http",
"proxyAddress": "1.2.3.4",
"proxyPort": "8080",
"proxyLogin": "user23",
"proxyPassword": "p4$w0rd",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...",
"data": {
"blob": "B7A24B7D-15EF-41...D3F5"
}
}
}
Response comes immediately: {"errorId":0,"taskId":"123456789"}. Save the taskId.
Get Result
Poll every 5–10 seconds:
Endpoint: POST https://api.2captcha.com/getTaskResult
json
{
"clientKey": "YOUR_API_KEY",
"taskId": "123456789"
}
Success response:
json
{
"errorId": 0,
"status": "ready",
"solution": {
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9..."
}
}
Step 5. Submitting the Token to the Website
The received token must be sent to the target website. The method depends on implementation, but there are two standard scenarios.
Option 1: Injection into Hidden Field (JS)
Most sites store the token in a hidden input. Find it and set the value before submitting the form.
javascript
// Find the field (name may vary: funcaptcha_token, arkose_token, etc.)
const tokenInput = document.querySelector('input[name*="funcaptcha"], input[name*="arkose"]');
if (tokenInput) {
tokenInput.value = "YOUR_TOKEN_FROM_API";
// Submit the form
tokenInput.closest('form').submit();
}
Option 2: Direct POST to Verification Endpoint
If the site uses AJAX verification, send the token directly to the verification URL.
python
import requests
verify_url = "https://target-site.com/api/verify-captcha"
payload = {
"funcaptcha_token": "YOUR_TOKEN_FROM_API",
"csrf_token": "CSRF_FROM_SESSION" # if required
}
headers = {
"User-Agent": "Mozilla/5.0...",
"Cookie": "session_id=abc123" # same session as when getting blob
}
response = requests.post(verify_url, json=payload, headers=headers)
print(response.json())
How to find the exact field/URL: Open DevTools → Network → solve captcha manually → find the request sent after clicking "Verify". Copy the field name and endpoint.
Step 6. Error ERROR_CAPTCHA_UNSOLVABLE
Worker failed the check. Common causes:
- Blob expired → get a new one
- Wrong websitePublicKey/URL → copy from current page
- userAgent empty or doesn't match proxy → sync the session
- Proxy blocked by Arkose → switch to residential
- New captcha type → send a report
Pro tip: If you get errors with correct parameters, wait 60–90 sec. Sometimes Arkose runs background session checks.
| Cause | Solution |
|---|---|
| Old blob | Refresh, get new one |
| Wrong websitePublicKey | Copy from DOM |
| Proxy/userAgent mismatch | Sync to one session |
| New task type | Send report |
Log responses from getTaskResult—after a week you'll see error patterns.
Step 7. Alternative Methods: Detailed GridTask Guide
Sometimes getting a token for Funcaptcha becomes an insurmountable task due to complex captcha implementation on the website: dynamic iframe loading, parameter obfuscation, or blob extraction blocking. In this case, you should resort to an alternative solving method—the grid method (GridTask).
When to Use GridTask Instead of the Standard Method
- The site doesn't allow blob extraction due to CSP or obfuscation
- Captcha loads inside a cross-domain iframe with limited access
- You're working with a mobile site version where request structures differ
- The standard method returns UNSOLVABLE despite correct parameters
- You're automating interactions across multiple domains and want a universal solution
How GridTask Works
Instead of the blob token, you submit the full captcha image and a text instruction in English. The system uses computer vision and human verification to determine click coordinates.
Step-by-Step Algorithm
1. Get the Captcha Image
- In DevTools → Network, find the request to https://client-api.arkoselabs.com/rtig/image... or https://*.arkoselabs.com/fc/gc/?...
- The response contains a PNG/JPG image—download it
- Convert to base64 (Python: base64.b64encode(image_data).decode())
- Ensure the image isn't cropped—the entire task area must be visible
2. Get the Text Instruction
javascript
// Instruction is usually in the task header
var taskElement = document.querySelector('.sc-1io4bok-0, .challenge-text, [class*="instruction"]');
var taskText = taskElement ? (taskElement.textContent || taskElement.innerText).trim() : '';
- Instruction must be in English! If the site uses another language—translate the key part
- Examples of correct instructions:
- pick the image where the darts add up to 8
- select all pictures with bicycles
- click on the animal that lives in water
3. Submit the Task
json
{
"clientKey": "YOUR_API_KEY",
"task": {
"type": "GridTask",
"body": "/9j/4AAQSkZJRgABAQEAYABgAAD/4QBoRXxpZgAA...",
"comment": "pick the image where the darts add up to 8",
"imgType": "funcaptcha"
}
}
Optional parameters:
- softId — your software identifier for statistics
- callbackUrl — URL to receive results via webhook
4. Get and Process the Response
json
{
"status": 1,
"request": "click:3"
}
The number after click: is how many clicks you need to emulate on the page. For multi-answer tasks, the format may be click:2,5,7.
How to Emulate Clicks on the Page
After receiving the response, you need to programmatically click the correct grid cells. Most Funcaptcha instances use 2x2, 3x3, or 4x4 grids.
javascript
// Example for 3x3 grid
const clicks = "3"; // or "2,5,7" for multiple clicks
const indices = clicks.split(',').map(Number);
// Find the answer options container
const gridContainer = document.querySelector('.rc-imageselect-table, [class*="grid"], .challenge-body');
const cells = gridContainer.querySelectorAll('img, .rc-imageselect-tile, [role="button"]');
indices.forEach(index => {
if (cells[index - 1]) {
cells[index - 1].click();
}
});
// After clicks, often need to press the Verify button
setTimeout(() => {
const verifyBtn = document.querySelector('.rc-button-submit, button[type="submit"], [class*="verify"]');
if (verifyBtn) verifyBtn.click();
}, 500);
Common Issues and Solutions
| Problem | Solution |
|---|---|
| Image is cropped or low quality | Screenshot the entire captcha area; ensure resolution is at least 300x300px |
| Instruction in Russian/other language | Translate only the task essence to English, not word-for-word |
| Response received but site rejects it | Verify clicks emulate the coordinates the site expects; add delays between clicks |
| Low recognition accuracy | Clarify the instruction: instead of "pick animals", write "select all images containing cats" |
| Task timeout | GridTask takes longer to solve (up to 60 sec); configure a longer polling interval |
Important: The Funcaptcha_compare method (for icon-matching tasks) is temporarily unavailable. If your site uses this type—contact support.
Read more about both methods: https://2
captcha.com/blog/funcaptcha-bypass-2-ways-solutions
Step 8. Reports
Report = balance refund + system learning.
When to send:
- Site rejected correct answer
- Worker missed (wrong coordinates)
- New task type appeared
How:
POST https://api.2captcha.com/reportCorrect
{
"clientKey": "YOUR_API_KEY",
"taskId": "123456789"
}
Send within 30 seconds—otherwise the task is considered accepted.
Checklist
- websitePublicKey is current
- websiteURL matches
- userAgent and proxy belong to the same session
- blob is fresh (< 3 min)
- Token is submitted to the correct field/endpoint
- Logging is configured
- Reports are working
- Test on 10–20 captchas passed
Code
Ready-to-use implementation examples for popular programming languages are available in the official repository:
github.com/2Captcha/api
Basic Python Example (Standard Method with Blob)
python
import requests
import time
API_KEY = "YOUR_API_KEY"
CREATE_TASK_URL = f"https://api.2captcha.com/createTask"
GET_RESULT_URL = f"https://api.2captcha.com/getTaskResult"
def solve_funcaptcha(website_url, public_key, blob, user_agent, proxy):
# Create task
create_payload = {
"clientKey": API_KEY,
"task": {
"type": "FunCaptchaTask",
"websiteURL": website_url,
"websitePublicKey": public_key,
"proxyType": proxy["type"],
"proxyAddress": proxy["address"],
"proxyPort": proxy["port"],
"proxyLogin": proxy.get("login"),
"proxyPassword": proxy.get("password"),
"userAgent": user_agent,
"data": {"blob": blob}
}
}
response = requests.post(CREATE_TASK_URL, json=create_payload)
result = response.json()
if result.get("errorId") != 0:
raise Exception(f"Task creation error: {result}")
task_id = result["taskId"]
# Poll for result
while True:
time.sleep(5)
result_payload = {
"clientKey": API_KEY,
"taskId": task_id
}
response = requests.post(GET_RESULT_URL, json=result_payload)
result = response.json()
if result.get("status") == "ready":
return result["solution"]["token"]
elif result.get("errorId") != 0:
raise Exception(f"Solving error: {result}")
# Usage
token = solve_funcaptcha(
website_url="https://target-site.com/page",
public_key="YOUR_PUBLIC_KEY",
blob="B7A24B7D-15EF-41...D3F5",
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64)...",
proxy={
"type": "http",
"address": "1.2.3.4",
"port": "8080",
"login": "user",
"password": "pass"
}
)
print(f"Token received: {token[:50]}...")
Bottom Line
Working with Funcaptcha requires attention to detail, but with proper setup it becomes predictable. Key principles for stable solving:
- Data freshness — blob lives for minutes, publicKey can change after site updates. Always extract parameters from the current session.
- Session unity — userAgent, proxy, cookies, and geo must match each other. Desynchronization is a common cause of UNSOLVABLE.
- Backup plan — if the standard blob method fails, GridTask lets you bypass limitations via visual recognition.
- Feedback loop — reports not only refund balance but also help the system adapt to new task types.
- Testing — before launching mass automation, verify the chain on 20–30 requests with logging at each stage.
Funcaptcha continues to evolve, but an approach based on current parameters, synchronized sessions, and readiness to switch between methods ensures reliability even amid frequent security updates.
Recommended implementation order:
- Set up blob retrieval and basic task submission
- Test token injection on the target site
- Add error handling and logging
- Implement the reporting mechanism for balance refunds
- Add GridTask as a fallback method for main method failures
- Set up monitoring and alerts for error rate spikes
Phased debugging saves time and balance long-term, while modular code architecture allows quick adaptation to changes in Arkose Labs' protection.