Was this helpful?
How to bypass MTCaptcha
Punisher in the IT cartel
Introduction
MTCaptcha is a modern anti-automation system used on many websites and mobile applications. Unlike classic text or image CAPTCHAs, MTCaptcha operates on a token-based mechanism: the widget analyzes user behavior in real-time, and upon successful verification, returns a cryptographic token mtcaptcha-verifiedtoken, which must be sent to the target website's server to confirm the legitimacy of the request.
In this guide, we will thoroughly explain how to automate MTCaptcha solving via API, what parameters are required, how to integrate the solution into Python scripts, and what to do if the standard token-based method doesn't work.
How MTCaptcha works
| Characteristic | Description |
|---|---|
| Verification Type | Token-based (JavaScript widget) |
| Visual Element | Text CAPTCHA, invisible verification, or adaptive challenge |
| Protection Mechanism | Behavioral signal collection, fingerprint analysis, proof-of-work, Threat SPECT |
| Verification Result | Generation of a one-time token mtcaptcha-verifiedtoken |
| Token Lifetime | Minimum 50 seconds, typically up to 120 seconds |
MTCaptcha offers several operating modes:
- Modern Mini — compact widget for forms
- Invisible Captcha — fully invisible verification for most users
- Adaptive Complexity — dynamic difficulty increase when bot activity is suspected
Required parameters for task submission
For proper functionality, you must provide a minimal set of parameters. Depending on the task type selected, the structure may vary slightly.
Basic parameters (for all task types)
| Property | Type | Required | Description |
|---|---|---|---|
| type | String | Yes | Task type: MtCaptchaTaskProxyless or MtCaptchaTask |
| websiteURL | String | Yes | Full URL of the page where the CAPTCHA widget is displayed |
| websiteKey | String | Yes | Public site key (SiteKey), extracted from the page source code |
Proxy parameters (only for MtCaptchaTask)
| Property | Type | Required | Description |
|---|---|---|---|
| proxyType | String | Yes | Protocol: http, https, or socks5 |
| proxyAddress | String | Yes | IP address or domain name of the proxy server |
| proxyPort | Integer | Yes | Proxy server port |
| proxyLogin | String | No | Login for authentication (if required) |
| proxyPassword | String | No | Password for authentication (if required) |
The
MtCaptchaTaskProxylesstype is recommended for websites without strict IP binding. TheMtCaptchaTasktype is required if the target resource validates that the IP address matches between the CAPTCHA request and form submission.
Step by Step Guide: API integration
Step 1. Extracting the websiteKey
- Open the target website in a browser and press
F12to open Developer Tools - Navigate to the Elements (or Inspector) tab
- Locate the CAPTCHA container. It typically looks like this:
html
<!-- MTCaptcha Anchor DOM -->
<div class="mtcaptcha" data-mtcaptcha-site-key="MTPublic-ExampleKey123"></div>
Or in the script configuration:
html
<script>
var mtcaptchaConfig = {
"sitekey": "MTPublic-ExampleKey123"
};
</script>
- Copy the
sitekeyvalue. This is yourwebsiteKey.
If the key is not found in the markup, open the Network tab, reload the page, and filter requests by
mtcaptcha. Thesitekeyis often passed in the script initialization parameters.
Step 2. Creating a task
Send a POST request to the task creation endpoint:
https://api.2captcha.com/createTask
Example request body (without proxy):
json
{
"clientKey": "YOUR_API_KEY",
"task": {
"type": "MtCaptchaTaskProxyless",
"websiteURL": "https://example.com/login",
"websiteKey": "MTPublic-ExampleKey123"
}
}
Example request body (with proxy):
json
{
"clientKey": "YOUR_API_KEY",
"task": {
"type": "MtCaptchaTask",
"websiteURL": "https://example.com/login",
"websiteKey": "MTPublic-ExampleKey123",
"proxyType": "http",
"proxyAddress": "198.51.100.10",
"proxyPort": 8080,
"proxyLogin": "user",
"proxyPassword": "secret"
}
}
Step 3. Receiving the taskId
Upon successful task acceptance, the server will return:
json
{
"errorId": 0,
"taskId": "a1b2c3d4e5f6g7h8i9j0"
}
Save the taskId for subsequent polling.
Step 4. Polling for results
Periodically send a POST request to:
https://api.2captcha.com/getTaskResult
Request body:
json
{
"clientKey": "YOUR_API_KEY",
"taskId": "a1b2c3d4e5f6g7h8i9j0"
}
Successful response:
json
{
"errorId": 0,
"status": "ready",
"solution": {
"token": "v1(8f3a1c,7b2d9e,MTPublic-ExampleKey123,4a5b6c7d8e9f0...)"
},
"cost": "0.00299",
"ip": "198.51.100.10",
"createTime": 1714489200,
"endTime": 1714489212
}
Step 5. Using the token in the target request
The received token must be submitted to the website in a hidden form field named mtcaptcha-verifiedtoken:
html
<input type="hidden" name="mtcaptcha-verifiedtoken" value="v1(8f3a1c,7b2d9e,...)">
Or in the POST request body:
javascript
fetch("https://example.com/api/verify", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: `mtcaptcha-verifiedtoken=v1(8f3a1c,7b2d9e,...)&username=test&password=123`
});
The token is single-use and has a short lifetime (minimum 50 seconds). Submit it to the target request immediately after receiving it.
Python code examples
Option 1: Pure Python (requests library)
python
import requests
import time
API_KEY = "YOUR_API_KEY"
CREATE_URL = "https://api.2captcha.com/createTask"
RESULT_URL = "https://api.2captcha.com/getTaskResult"
def solve_mtcaptcha(url: str, sitekey: str, proxy: dict = None) -> str:
task = {
"clientKey": API_KEY,
"task": {
"type": "MtCaptchaTaskProxyless" if not proxy else "MtCaptchaTask",
"websiteURL": url,
"websiteKey": sitekey
}
}
if proxy:
task["task"].update({
"proxyType": proxy.get("type", "http"),
"proxyAddress": proxy["address"],
"proxyPort": proxy["port"],
"proxyLogin": proxy.get("login"),
"proxyPassword": proxy.get("password")
})
# Create task
resp = requests.post(CREATE_URL, json=task).json()
if resp["errorId"] != 0:
raise RuntimeError(f"Task creation error: {resp}")
task_id = resp["taskId"]
# Wait for solution
for _ in range(24): # up to 120 seconds
time.sleep(5)
res = requests.post(RESULT_URL, json={
"clientKey": API_KEY,
"taskId": task_id
}).json()
if res["status"] == "ready":
return res["solution"]["token"]
if res["errorId"] != 0:
raise RuntimeError(f"Solution error: {res}")
raise TimeoutError("Solution timeout exceeded")
# Usage example
token = solve_mtcaptcha(
url="https://example.com/login",
sitekey="MTPublic-ExampleKey123"
)
print(f"Ready token: {token}")
Option 2: Official Python Library
Installation: pip install 2captcha-python
python
from twocaptcha import TwoCaptcha
solver = TwoCaptcha('YOUR_API_KEY')
# Solve without proxy
result = solver.mtcaptcha(
websiteURL='https://example.com/login',
websiteKey='MTPublic-ExampleKey123'
)
print(f"Token: {result['code']}")
# Solve with proxy
result = solver.mtcaptcha(
websiteURL='https://example.com/login',
websiteKey='MTPublic-ExampleKey123',
proxyType='http',
proxyAddress='198.51.100.10',
proxyPort='8080',
proxyLogin='user',
proxyPassword='secret'
)
print(f"Token: {result['code']}")
Library source code: GitHub
Alternative method: when tokens don't work
In some configurations, the target website may reject tokens obtained via the standard API, or the widget may display a non-standard image/text challenge. If you cannot solve the CAPTCHA using tokens, you can use an alternative solving method: Normal CAPTCHA
When to use this method:
- The website does not accept tokens obtained via API
- MTCaptcha displays as a text image
- You need to recognize a text CAPTCHA embedded in the widget
How it works:
- Use browser automation (Selenium, Playwright, Puppeteer) to capture a screenshot of the CAPTCHA area
- Encode the image to Base64
- Submit an
ImageToTextTasktype task - Use the returned text as the answer in the corresponding form field
Example request:
json
{
"clientKey": "YOUR_API_KEY",
"task": {
"type": "ImageToTextTask",
"body": "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAA...",
"phrase": false,
"case": false,
"numeric": 0
}
}
Python example:
python
import base64
from twocaptcha import TwoCaptcha
solver = TwoCaptcha('YOUR_API_KEY')
# From file
result = solver.normal('screenshot.png')
print(f"Answer: {result['code']}")
# From Base64 string
with open('screenshot.png', 'rb') as f:
b64 = base64.b64encode(f.read()).decode()
result = solver.normal(b64)
print(f"Answer: {result['code']}")
This approach is useful for non-standard widget implementations, outdated protection versions, or situations where server-side validation expects exact text input.
Error handling and recommendations
Common error codes
| Error Code | Cause | Solution |
|---|---|---|
| ERROR_WRONG_USER_KEY | Invalid API key | Verify the key in your account dashboard |
| ERROR_NO_SLOT_AVAILABLE | No available workers | Retry the request after 10–15 seconds |
| ERROR_CAPTCHA_UNSOLVABLE | Current instance cannot be solved | Refresh websiteKey, change proxy, or use alternative method |
| ERROR_BAD_PARAMETERS | JSON structure error or missing fields | Compare request with documentation |
| ERROR_ZERO_BALANCE | Insufficient funds | Top up your account balance |
Practical tips for stability
Synchronize request context
MTCaptcha may bind the token to User-Agent, headers, and IP. Send the target request with the same parameters used when creating the task.
Respect timing constraints
Tokens are valid for at least 50 seconds, typically up to 120 seconds. Do not add delays between receiving the solution and submitting the form.
Handle dynamic sitekeys
On some websites, the key is generated on each page load. Always parse the fresh page version before creating a task.
Implement retries
Network errors and temporary service load are normal. Add 2–3 retry attempts with exponential backoff.
Emulate human behavior
Even with a valid token, the website may reject requests suspected of being bot-driven. Use realistic headers, random pauses between actions, and avoid sending batch requests without parameter rotation.
Useful Links
Conclusion
Automated MTCaptcha solving boils down to correctly extracting the websiteKey, submitting the task to the API, and quickly inserting the received token into the mtcaptcha-verifiedtoken field. The key success factor is maintaining context: the token must be used under the same conditions in which it was generated.
If the standard token-based method fails validation, switch to image recognition via the ImageToTextTask method. This is a reliable fallback option for complex or non-standard protection implementations.
Start integration with test pages, log server responses, and implement retry mechanisms—this will ensure stable automation performance even when protection logic changes.