Skip to content
voidcaptcha

Task type

reCAPTCHA Mobile solver API for Android apps

reCAPTCHA Mobile is the reCAPTCHA Enterprise check built into Android apps through Google’s com.google.android.recaptcha SDK, and its tokens are not interchangeable with web reCAPTCHA tokens. VoidCaptcha mints those mobile tokens from the app’s site key and package name, proxyless with ReCaptchaMobileDirect or through your proxy with ReCaptchaMobile, and returns the token with the Dalvik User-Agent to send it under, at $1.00 per 1,000 successful solves.

Mobile reCAPTCHA Enterprise is a different protocol from the web one: an Android app calls the com.google.android.recaptcha SDK, which talks to Google over its own binary API rather than the browser challenge flow. A token minted for a web site key will not pass a mobile check and the reverse is also true, so this is a separate type rather than a flag on reCAPTCHA v3. Send the app package name you are solving for and the action the app uses. ReCaptchaMobileDirect is proxyless — it mints from our IP, needs no proxy, and is the one to start with; ReCaptchaMobile mints through a proxy you supply, for when the token has to come from a particular country or carrier. The response carries the Dalvik User-Agent the token was minted as: send that same User-Agent with the token or the check will refuse it.

Tip

Send task.type as ReCaptchaMobile and the solution arrives in solution.token.

A site that will not solve is worth telling us about — coverage is per target as much as per type. The quickest route is Telegram (@VoidCaptchaSupport), where someone usually answers within minutes. You can also open a ticket from your dashboard or email [email protected]. Send the URL and the site key either way.

task.type
ReCaptchaMobile
Median
173ms
over 8,376,269 solves, 30d
Success
99.9%
Price / 1k
$1.00
$0.0010 each
Proxy
Not needed

Solve request#

Solving reCAPTCHA Mobile is a single synchronous call. You post one task object and the response carries the finished solution — no task id to store, nothing to poll for.

POSThttps://api.voidcaptcha.com/v1/getResult

The connection is held open for the whole solve, which for this type runs a median of 173ms. Set a client timeout that covers it — the default socket timeout in most HTTP libraries is shorter than the work. If holding a connection that long does not suit your worker fleet, the same task goes to /v1/createTask and you collect it from /v1/checkTask instead.

When to use it#

  • Automating an Android app flow that gates sign-in behind mobile reCAPTCHA
  • Testing a mobile API from a server, where no device and no browser exist
  • Checking that a mobile key rejects tokens minted for its web sibling

Task object structure#

These fields go inside task. The envelope around it — clientKey and the optional softId — is the same for every type and is described in the API reference.

PropertyTypeRequiredDescription
typestringRequiredLiteral "ReCaptchaMobile". Also accepts: ReCaptchaMobileDirect. Matching is case-insensitive.
site_keystringRequiredThe reCAPTCHA Enterprise site key the app was built with.e.g. 6LfXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
app_packagestringOptionalThe Android package name of the app. Google ties a mobile key to the package, so a mismatch scores badly even when a token comes back.e.g. com.example.app
actionstringOptionalThe action the app passes to the SDK. Must match exactly or verification fails, the same rule as reCAPTCHA v3.e.g. login
devicestringOptionalWhich platform to imitate. "android" today; "ios" is not solvable yet and is refused.e.g. android
device_modelstringOptionalPin the mint to one real device from our pool instead of letting us choose. Every profile is a coherent set of real Android build properties, so the model decides the whole fingerprint.e.g. Pixel_7_Pro
random_devicebooleanOptionalRotate across the device pool per solve rather than reusing one. Useful at volume on one site key.e.g. true
proxystringOptionalRequired for ReCaptchaMobile, and ignored entirely by ReCaptchaMobileDirect, which mints from our own IP. Use a sticky session.e.g. proxy.example.com:9090:user:pass

Example payload#

The whole body, assembled from the table above — copy it formatted to read, or on one line to paste straight into a terminal or a REST client. The values are placeholders: swap the key for your own and the URL and site key for the page you are solving.

POSThttps://api.voidcaptcha.com/v1/getResult
{
  "clientKey": "void_a1b2c3d4e5f60718293a4b5c6d7e8f90",
  "task": {
    "type": "ReCaptchaMobile",
    "site_key": "6LfXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "action": "login"
  }
}

Example request#

The smallest thing that gets a token back, in your language. Python and Node.js use the official client (pip install voidcaptcha, npm install voidcaptcha); every other language makes the HTTP call its standard library already has. The complete version, with the key read from the environment and the error envelope checked, is in Sample code at the bottom of this page.

Language choice is remembered across the whole site, so switching here carries to every other sample in the docs.

# pip install voidcaptcha
from voidcaptcha import VoidCaptcha

client = VoidCaptcha("void_a1b2c3d4e5f60718293a4b5c6d7e8f90")

result = client.recaptcha_mobile(
    site_key="6LfXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    action="login",
)

print(result.value)

Example response#

A successful solve returns errorId: 0 and a solution object. The result is in solution.token; alongside it is the userAgent the solve ran under.

solution carries those and nothing else — the gateway copies the result field, anything extra this type returns, and userAgent across, and drops the rest of whatever the solver sent. Timing arrives at the top level as elapsedMs, present only when the duration is known, beside cost and your remaining balance. The figures below are illustrative: nothing here is a published median.

JSON
{
  "errorId": 0,
  "status": "ready",
  "solution": {
    "token": "03AGdBq25V6…",
    "userAgent": "Mozilla/5.0 …"
  },
  "cost": "$0.0010",
  "balance": "$411.24",
  "elapsedMs": 4820
}

Send that userAgent on your downstream request as well — for the cookie-based types the result is bound to it and will be rejected under a different one.

Errors for this type#

The codes reCAPTCHA Mobile can return, on top of the shared authentication and billing set. Branch on errorCode, not on the HTTP status.

CodeHTTPMeaningRetry
ERROR_KEY_MISSING401No clientKey was supplied.Do not retry
ERROR_KEY_INVALID401The key does not exist or has been revoked.Do not retry
ERROR_KEY_SUSPENDED403The account attached to this key is suspended.Do not retry
ERROR_TYPE_NOT_ENABLED403This account is not enabled for the requested task type.Do not retry
ERROR_TYPE_UNSUPPORTED400task.type is not a recognised value.Do not retry
ERROR_REQUIRED_FIELD400A field this task type requires was absent.Do not retry
ERROR_SITEKEY_INVALID400The site key was malformed, or does not belong to that URL.Do not retry
ERROR_INSUFFICIENT_BALANCE402Your balance will not cover this solve.Do not retry
ERROR_THREAD_LIMIT429You have more solves in flight than your key permits.Retry with backoff
ERROR_RATE_LIMITED429Too many requests in a short window.Retry with backoff

Every code, with the fix for each, is on the error reference. A failed solve is never charged.

Sample code#

A complete file: key from the environment, task built, error envelope checked, result used. It calls the endpoint directly rather than through an SDK, so it works as a starting point in any language.

import os
import sys

import requests

API = "https://api.voidcaptcha.com/v1/getResult"

payload = {
    "clientKey": os.environ["VOIDCAPTCHA_KEY"],
    "task": {
        "type": "ReCaptchaMobile",
        "site_key": "6LfXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
        "action": "login"
    },
}

# The endpoint is synchronous: it holds the connection open for the whole
# solve, so the read timeout has to cover it, not just the handshake.
res = requests.post(API, json=payload, timeout=180).json()

if res["errorId"] != 0:
    sys.exit(f"{res['errorCode']}: {res['errorDescription']}")

solution = res["solution"]

# Carry the User-Agent downstream — the result was earned under it.
print(solution["token"])
print(solution["userAgent"])

Questions#

What is reCAPTCHA Mobile?

It is reCAPTCHA Enterprise for Android apps. The app calls Google’s com.google.android.recaptcha SDK, which talks to Google over its own API instead of the browser widget, and sends the resulting token to the app’s backend.

Can I use a web reCAPTCHA token in a mobile check?

No. A token minted for a web site key fails a mobile check and the reverse is also true, which is why reCAPTCHA Mobile is its own task type.

Do I need a proxy?

Not with ReCaptchaMobileDirect, which mints from our IP and ignores any proxy sent. Use ReCaptchaMobile with your own sticky proxy when the token has to come from a particular country or carrier.

What do I need to send?

The site_key the app was built with, plus the app_package name and the action the app passes to the SDK. Google ties a mobile key to its package, so a wrong package scores badly even when a token comes back.

Which User-Agent goes with the token?

The Dalvik User-Agent returned in the response. Send the token under that exact User-Agent or the check refuses it.

Is iOS supported?

Not yet. The device field accepts android today, and ios is refused.

Last updated on 2 August 2026