Tutorials

Debugging CAPTCHA API Calls with Charles Proxy

When your CAPTCHA integration returns unexpected errors, inspecting the raw HTTP traffic reveals what's really being sent and received. Charles Proxy sits between your code and CaptchaAI, letting you see every request, response, and timing detail.


Setup

1. Install Charles Proxy

Download from charlesproxy.com. Available on Windows, macOS, and Linux.

2. Enable SSL proxying

CaptchaAI uses HTTPS. To inspect encrypted traffic:

  1. ProxySSL Proxying SettingsAdd
  2. Host: ocr.captchaai.com, Port: 443
  3. HelpSSL ProxyingInstall Charles Root Certificate
  4. Trust the certificate in your OS certificate store

3. Configure your code to use Charles

Charles runs on localhost:8888 by default.

Python:

import requests

proxies = {
    "http": "http://localhost:8888",
    "https": "http://localhost:8888",
}

# Disable SSL verification for Charles (development only)
resp = requests.post(
    "https://ocr.captchaai.com/in.php",
    data={"key": "YOUR_API_KEY", "method": "userrecaptcha", "json": "1"},
    proxies=proxies,
    verify=False,
)

Node.js:

const axios = require('axios');
const HttpsProxyAgent = require('https-proxy-agent');

const agent = new HttpsProxyAgent('http://localhost:8888');

const resp = await axios.post('https://ocr.captchaai.com/in.php', null, {
  params: { key: 'YOUR_API_KEY', method: 'userrecaptcha', json: 1 },
  httpsAgent: agent,
});

What to inspect

Submit request (POST /in.php)

In Charles, click the request to /in.php. Check:

Tab What to verify
Request → Headers Content-Type is correct
Request → Body All required parameters present
Response → Body {"status":1,"request":"TASK_ID"} on success
Timing Request duration (should be <1s)

Common problems visible in Charles:

  • Missing method parameterERROR_BAD_PARAMETERS
  • Wrong Content-Type → Parameters not parsed
  • Empty googlekeyERROR_WRONG_GOOGLEKEY
  • Malformed JSON body → Use form data, not JSON body

Poll request (GET /res.php)

Check the poll requests:

  • Params: key, action=get, id=TASK_ID
  • Response: CAPCHA_NOT_READY (keep polling) or {"status":1,"request":"TOKEN"}
  • Timing: Each poll followed by your sleep interval

Debugging common issues

Issue: ERROR_WRONG_GOOGLEKEY

In Charles, look at the submit request body. Find the googlekey field:

# What Charles shows:
key=YOUR_API_KEY&method=userrecaptcha&googlekey=&pageurl=https://example.com&json=1
                                      ^^^^^^^^ empty!

Fix: The sitekey extraction failed upstream. Check your extraction code.

Issue: Token rejected by target site

Compare what CaptchaAI returned vs what you're injecting:

  1. In Charles, find the /res.php response with status: 1
  2. Copy the full token from request field
  3. Find the subsequent request to the target site
  4. Verify the token is in the form body as g-recaptcha-response

Issue: Requests timing out

Use Charles Sequence view to see timing:

POST /in.php     → 234ms ✓
GET  /res.php    → 189ms (CAPCHA_NOT_READY)
GET  /res.php    → 201ms (CAPCHA_NOT_READY)
GET  /res.php    → 195ms (CAPCHA_NOT_READY)
... 23 more ...
GET  /res.php    → 188ms (CAPCHA_NOT_READY)  ← never resolves

If it never resolves: check if the sitekey and page URL are correct.


Charles features for CAPTCHA debugging

Repeat request

Right-click any request → Repeat to re-send it. Useful for testing poll requests without re-running your entire script.

Breakpoints

Set a breakpoint on /in.php to inspect and modify the request before it's sent:

  1. ProxyBreakpoint SettingsAdd
  2. Host: ocr.captchaai.com, Path: /in.php
  3. Check Request
  4. Now your code pauses before sending — you can edit parameters

Map Local

Replace API responses with local files for testing:

  1. ToolsMap LocalAdd
  2. Map https://ocr.captchaai.com/res.php to a local JSON file
  3. Create mock_response.json:
{"status": 1, "request": "mock_token_for_testing"}

This lets you test your token injection code without using API credits.

Throttle

Simulate slow connections:

  1. ProxyThrottle Settings → Enable
  2. Set preset to 3G or EDGE-level speeds
  3. Test if your code handles slow responses and timeouts correctly

Alternatives to Charles

Tool Platform HTTPS Cost
Charles Proxy Win/Mac/Linux Requires cert install Paid (free trial)
mitmproxy Win/Mac/Linux Requires cert install Free
Fiddler Windows Built-in HTTPS decryption Free
Proxyman macOS One-click HTTPS setup Freemium

mitmproxy quick setup

# Install
pip install mitmproxy

# Run
mitmproxy --listen-port 8080

# Configure Python
proxies = {"https": "http://localhost:8080"}

Troubleshooting

Problem Cause Fix
SSL errors in code Charles cert not trusted Install Charles root cert; use verify=False for dev
No requests visible Code not using proxy Set proxy in requests/axios config
Garbled HTTPS response SSL proxying not enabled Add ocr.captchaai.com to SSL Proxying Settings
Charles slows requests Breakpoints enabled Disable breakpoints when not needed

FAQ

Should I use Charles in production?

No. Charles is a development and debugging tool. Use structured logging and monitoring for production observability.

Does routing through Charles affect CAPTCHA solving?

No. CaptchaAI doesn't see Charles as a proxy — your requests pass through transparently.


Debug and optimize your CaptchaAI integration

Get your API key at captchaai.com.


Full Working Code

Complete runnable examples for this article in Python, Node.js, PHP, Go, Java, C#, Ruby, Rust, Kotlin & Bash.

View on GitHub →

Discussions (0)

No comments yet.