Was this helpful?
How to bypass CaptchaFox with Playwright
CaptchaFox usually appears on the page before a form is submitted: until the check is passed, the form cannot be sent. A passed check produces a token, and the site verifies it.
In this guide we will go through the whole path in Playwright with Python: find the site key, send the task to the 2Captcha API and get the token. CaptchaFox has one detail that most often keeps the bypass from working on the first try: the captcha has two different servers, and their tokens are different. We will look at how to tell which one you need.
What You Will Need
- Python 3.7 or higher
- Installed Playwright
- 2Captcha account and API key
- Target page URL
- A proxy. It is required for CaptchaFox, the method does not work without one
Step 1. Installing Dependencies
Install the libraries and the Playwright browsers:
bash
pip install playwright 2captcha-python
playwright install chromium
Step 2. Browser Initialization and Page Navigation
A proxy is required for CaptchaFox, the request will not go through without one. Set the same proxy in the browser as well — the service solves the captcha from your address, and the addresses have to match. The second required parameter is the User-Agent: it has to be the same one you open the site with.
python
from playwright.sync_api import sync_playwright
PROXY = {"server": "http://1.2.3.4:8080", "username": "user23", "password": "p4$w0rd"}
with sync_playwright() as p:
browser = p.chromium.launch(headless=False, proxy=PROXY)
page = browser.new_page()
page.goto("https://mysite.com/page/with/captchafox")
page.wait_for_load_state("networkidle")
Step 3. Extracting the Site Key
Every site with CaptchaFox has its own key, and on the page it sits in the key parameter. It starts with sk_ and looks like this: sk_xtNxpk6fCdFbxh1_xJeGflSdCE9tn99G. You can find it in the page source or in the network requests the page sends while loading.
The simplest way is to search the page source:
python
import re
html = page.content()
match = re.search(r"sk_[A-Za-z0-9_-]+", html)
if match is None:
raise RuntimeError("Site key not found, look for it on the Network tab")
website_key = match.group(0)
page_url = page.url
user_agent = page.evaluate("navigator.userAgent")
print("Site key:", website_key)
If the key is not in the page source, open the developer tools, go to the Network tab, reload the page and find the request to the captcha server. The key will be among its parameters.
Step 4. Choosing the Captcha Server
CaptchaFox has two servers, and their tokens come in different formats:
https://cdn.captchafox.com/— the default address;https://s.uicdn.com/mampkg/@mamdev/core.frontend.libs.captchafox/— here the token arrives with theMAM_prefix.
A site accepts a token only from its own server, so the request has to carry the same address the page works with. Check on the Network tab where the page loads the captcha script from.
python
api_server = "https://cdn.captchafox.com/"
if page.locator('script[src*="s.uicdn.com"]').first.count() > 0:
api_server = "https://s.uicdn.com/mampkg/@mamdev/core.frontend.libs.captchafox/"
print("Captcha server:", api_server)
Step 5. Sending the Task to the API and Getting the Token
The task is created by the official Python SDK. The proxy and the User-Agent are required here, while api_server is passed only when it differs from the default.
python
import os
from twocaptcha import TwoCaptcha
api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY')
solver = TwoCaptcha(api_key)
result = solver.captchafox(
sitekey=website_key,
pageurl=page_url,
userAgent=user_agent,
proxy={'type': 'HTTP', 'uri': 'user23:p4$w0rd@1.2.3.4:8080'},
api_server=api_server
)
token = result['code']
print("Token received:", token)
In the API the field is called websiteKey, in the SDK — sitekey. The value is the same. The same goes for the server address: in the API it is apiServer, in the SDK — api_server.
The response holds a single token:
json
{
"errorId": 0,
"status": "ready",
"solution": {
"token": "7828075fb55ecbd9146745ee6f2bec475b88076d36e23050f1fb28359ffca15d"
}
}
Alternative (direct HTTP request):
If you don't use the SDK, send the request with curl or the requests library. There is only one task type, CaptchaFoxTask, and the proxy is required there as well.
bash
curl -X POST https://api.2captcha.com/createTask \
-H "Content-Type: application/json" \
-d '{
"clientKey": "YOUR_API_KEY",
"task": {
"type": "CaptchaFoxTask",
"websiteURL": "https://mysite.com/page/with/captchafox",
"websiteKey": "sk_xtNxpk6fCdFbxh1_xJeGflSdCE9tn99G",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36",
"proxyType": "http",
"proxyAddress": "1.2.3.4",
"proxyPort": "8080",
"proxyLogin": "user23",
"proxyPassword": "p4$w0rd"
}
}'
Step 6. Injecting the Token and Submitting the Form
You can find the right place for the token in a single manual pass: complete the captcha yourself with the Network tab open and see which field or which request the token ended up in.
There are usually two options. If the page has a hidden field, write the token into it. Put your own selector in place of SELECTOR_TOKEN.
python
page.evaluate("""(token) => {
const field = document.querySelector('SELECTOR_TOKEN');
if (!field) {
throw new Error('The token field was not found on the page');
}
field.value = token;
}""", token)
If there is no field and the captcha calls a callback function, call it yourself. Put your own function name in place of CALLBACK.
python
page.evaluate("""(token) => {
if (typeof CALLBACK !== 'function') {
throw new Error('The callback function was not found');
}
CALLBACK(token);
}""", token)
The check is needed in both cases: without it the script will submit the form with no token and report a successful submission.
Then submit the form. Put in your own button selector.
python
page.click("button[type='submit']")
page.wait_for_load_state("networkidle")
The result is worth reporting to the service. The SDK has the report method for this, the API has reportCorrect and reportIncorrect. The task identifier is in the same response as the token: solver.report(result['captchaId'], True).
Complete Working Example (Python)
python
import os
import re
from playwright.sync_api import sync_playwright
from twocaptcha import TwoCaptcha
API_KEY = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY')
TARGET_URL = "https://mysite.com/page/with/captchafox"
PROXY_BROWSER = {"server": "http://1.2.3.4:8080", "username": "user23", "password": "p4$w0rd"}
PROXY_API = {'type': 'HTTP', 'uri': 'user23:p4$w0rd@1.2.3.4:8080'}
def solve_captchafox():
solver = TwoCaptcha(API_KEY)
with sync_playwright() as p:
browser = p.chromium.launch(headless=False, proxy=PROXY_BROWSER)
page = browser.new_page()
try:
page.goto(TARGET_URL)
page.wait_for_load_state("networkidle")
# 1. Look for the site key
match = re.search(r"sk_[A-Za-z0-9_-]+", page.content())
if match is None:
raise RuntimeError("Site key not found, look for it on the Network tab")
website_key = match.group(0)
user_agent = page.evaluate("navigator.userAgent")
print("Site key:", website_key)
# 2. Determine the captcha server
api_server = "https://cdn.captchafox.com/"
if page.locator('script[src*="s.uicdn.com"]').first.count() > 0:
api_server = "https://s.uicdn.com/mampkg/@mamdev/core.frontend.libs.captchafox/"
print("Captcha server:", api_server)
# 3. Send the task to the API
print("Sending the task to the API...")
result = solver.captchafox(
sitekey=website_key,
pageurl=page.url,
userAgent=user_agent,
proxy=PROXY_API,
api_server=api_server
)
token = result['code']
print("Token received:", token)
# 4. Put the code from Step 6 here, for your own field or callback
# 5. Submit the form
page.click("button[type='submit']")
page.wait_for_load_state("networkidle")
print("Form submitted.")
page.wait_for_timeout(3000) # Pause for visual verification
# 6. Report the result. True if the site accepted the token, otherwise False
solver.report(result['captchaId'], True)
except Exception as e:
print(f"Error: {e}")
finally:
browser.close()
if __name__ == "__main__":
solve_captchafox()
Troubleshooting Common Issues
- The site does not accept the token even though the task was solved. There can be several reasons. Either the wrong captcha server was chosen — check Step 4, a token with the
MAM_prefix only fits a site that works with the second server. Or it is the proxy: the service solves the captcha from the address you passed in the request, so the browser and the API have to work through the same working proxy. - The task is not created or comes back with an error. Check the proxy first. Leave out
typeoruriand the script will fail with aKeyError. - The script does not find the captcha. The widget may load inside an iframe. Reach its contents through
page.frame_locator.
If the API returned an error code, its description is on the Error Codes page, linked at the end.
Conclusion
The hard part of CaptchaFox is not the captcha itself but the fact that it has two servers whose tokens come in different formats. Get the address wrong and the task will be solved and paid for, while the site will not accept the solution.
Send your reports through reportCorrect and reportIncorrect: they let the service tell which solutions did not work.
The full parameter reference is on the documentation page: https://2captcha.com/api-docs/captchafox
Useful Links
- 2Captcha API documentation for CaptchaFox: https://2captcha.com/api-docs/captchafox
- How to bypass CaptchaFox: https://2captcha.com/p/captchafox-solver
- Using proxies: https://2captcha.com/api-docs/proxy
- Error Codes: https://2captcha.com/api-docs/error-codes
- Debugging: https://2captcha.com/api-docs/debugging
- 2Captcha Python SDK on GitHub: https://github.com/2captcha/2captcha-python