Aries Solver

Documentation

Aries Solver solves reCAPTCHA v3 and Cloudflare Turnstile, and sends HTTP requests with a real browser's TLS fingerprint. Each is a single HTTP request. There is nothing to poll: the response either carries the result or an error explaining what to change.

Every request is JSON in and JSON out, and is charged only when it succeeds.

Your key holds one balance, in US dollars, shared by every endpoint. Each successful request deducts that endpoint's own price, listed below, so the same balance can be spent on any mix of them.

EndpointWhat it doesPrice
POST /getRecaptchaV3Solves a reCAPTCHA v3$2.00 per 1,000 tokens
POST /solveSolves a Cloudflare Turnstile widget$0.70 per 1,000 tokens
POST /tlsMakes an HTTP request with a browser TLS fingerprint$0.70 per 1,000 requests

Base URL

BASE __BASE__

Every endpoint also exists under a /v1 prefix. Both forms behave identically, so /getRecaptchaV3 and /v1/getRecaptchaV3 are the same endpoint.

Authentication

Pass your API key with every request. Keys look like ar_live_ followed by 48 hexadecimal characters.

Any one of these is accepted.
MethodExample
HeaderX-API-Key: ar_live_…
Bearer tokenAuthorization: Bearer ar_live_…
Request body{"clientKey": "ar_live_…"}
Keep your key on your server

A key spends your balance. Never ship it in a browser bundle or a mobile app. If a key leaks, ask for a replacement on Telegram and the old one is revoked immediately.

Solve a reCAPTCHA v3

reCAPTCHA v3 and Enterprise

POST __BASE__/getRecaptchaV3

Submits a target page and returns a token for it. The call blocks until the solve finishes or the time budget runs out. Each solved token costs $0.002 ($2.00 per 1,000).

Request body
{
  "url": "https://example.com/login",
  "sitekey": "6LfCVLAUAAAAALFwwRnnCJ12",
  "proxy": "http://user:pass@host:8080",
  "action": "login",
  "enterprise": false
}

Request parameters

Field Type Required Description
url string Yes Full URL of the page holding the captcha, including the scheme. For example https://example.com/login.
sitekey string Yes The reCAPTCHA v3 site key from the target page. Usually begins with 6L.
proxy string Yes Proxy the solve runs through, with scheme and port: scheme://user:pass@host:port. Supports http, https, socks4 and socks5.
action string No The action name the page expects, such as login or submit. Send it when you know it, because scores are often tied to it.
enterprise boolean No Set to true for reCAPTCHA Enterprise. Leave it out for standard v3.
title string No Page title to present during the solve. Derived from the domain when omitted.

Proxy format

The scheme and the port are both required. These are valid:

Accepted proxy strings
http://user:pass@198.51.100.10:8080
https://user:pass@198.51.100.10:8443
socks5://user:pass@198.51.100.10:1080
http://198.51.100.10:8080

A bare host:port, or a scheme with no port, is rejected with Invalid proxy format before the solve starts.

Response

A solved request answers 200 with the token and the fingerprint of the browser that produced it.

200 OK
{
  "status": "success",
  "data": {
    "token": "03AFcWeA5_zX2...",
    "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ... Chrome/145.0.0.0 Safari/537.36",
    "sec_ch_ua": "\"Chromium\";v=\"145\", \"Google Chrome\";v=\"145\"",
    "sec_ch_ua_platform": "\"Windows\"",
    "sec_ch_ua_mobile": "?0",
    "accept_lang": "en-US,en;q=0.9"
  },
  "credits": 998,
  "balance_usd": 1.996
}
FieldDescription
statussuccess on a solve, error otherwise.
data.tokenThe reCAPTCHA v3 token to submit to the target site.
data.user_agentUser agent of the solving browser. Send this with your request.
data.sec_ch_uaClient hint brand list matching the solving browser.
data.sec_ch_ua_platformClient hint platform, for example "Windows".
data.sec_ch_ua_mobileClient hint mobile flag, ?0 or ?1.
data.accept_langAccept-Language of the solving browser.
creditsHow many more requests of this endpoint your balance covers, after this one was charged.
balance_usdYour balance in US dollars after this request was charged.

Errors use the same envelope with a message instead of data:

Error shape
{
  "status": "error",
  "message": "Insufficient credits"
}

Using the token

The token is bound to the browser that produced it. Send the returned fingerprint alongside it or the target site may score the request poorly.

  • Set your request's User-Agent to data.user_agent.
  • Send Sec-CH-UA, Sec-CH-UA-Platform and Sec-CH-UA-Mobile from the matching fields.
  • Set Accept-Language to data.accept_lang.
  • Use the same proxy you passed to the solve.
Tokens expire in about two minutes

Request the solve at the moment you need it rather than building a pool in advance. A token that has expired is rejected by the target site, not by this API.

Code examples

curl -X POST __BASE__/getRecaptchaV3 \
  -H "X-API-Key: ar_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "url": "https://example.com/login",
        "sitekey": "6LfCVLAUAAAAALFwwRnnCJ12",
        "proxy": "http://user:pass@host:8080",
        "action": "login"
      }'

Cloudflare Turnstile API

Solve Turnstile widgets through POST /solve

Solve Cloudflare Turnstile widgets for any website. Provide the page URL and the widget's sitekey, and get back a valid Turnstile token. Each solved token costs $0.0007 ($0.70 per 1,000). Failed solves cost nothing.

Turnstile is solved through POST /solve with "type": "turnstile".

Endpoint

POST __BASE__/solve

Authentication

Requires the X-API-Key header with your API key.

Request

Content-Type: application/json

Request body
{
  "type": "turnstile",
  "site_key": "0x4AAAAAAABkMYinukE8nzY",
  "url": "https://example.com/login",
  "proxy": "http://user:pass@198.51.100.10:8080"
}

Turnstile parameters

Field Type Required Description
type string Yes Always "turnstile".
site_key string Yes The widget's data-sitekey, for example 0x4AAAAAAA....
url string Yes The page the widget is embedded in, including the scheme.
proxy string No scheme://[user:pass@]host:port, where the scheme is http, https or socks5. Without one, the solve runs from our own network.
action string No The widget's data-action, if the site sets one.
cdata string No The widget's data-cdata, if the site sets one.
Mind the field name

Turnstile takes site_key, with an underscore.

Finding the sitekey

It sits on the widget itself: a div with the class cf-turnstile, or the options passed to turnstile.render(). Copy data-action and data-cdata from the same place when they are there.

In the target page
<div class="cf-turnstile" data-sitekey="0x4AAAAAAABkMYinukE8nzY" data-action="login"></div>

Turnstile response

A solved widget answers 200:

Success response
{
  "status": "success",
  "data": {
    "token": "0.r8C5bJ2kX..."
  },
  "credits": 9.9993
}

A failure answers with the HTTP status from Turnstile errors and a message in data.message:

Error response
{
  "status": "error",
  "data": {
    "message": "Cloudflare rejected site_key for this url"
  },
  "credits": 10
}
FieldTypeDescription
data.tokenstringThe solved Turnstile token. Submit it as cf-turnstile-response.
data.messagestringOn an error, what went wrong.
creditsnumberYour remaining balance, in US dollars. Left out when the key itself is refused.

When the solve produced them, data also carries user_agent, sec_ch_ua, sec_ch_ua_platform, sec_ch_ua_mobile and accept_lang. Send them with your target request when they are there, through the same proxy, as described in Using the token.

Turnstile examples

import requests

API = "__BASE__/solve"
KEY = "ar_live_YOUR_KEY"

r = requests.post(API, headers={"X-API-Key": KEY}, json={
    "type": "turnstile",
    "site_key": "0x4AAAAAAABkMYinukE8nzY",
    "url": "https://example.com/login",
}, timeout=180)

data = r.json()
if data["status"] == "success":
    token = data["data"]["token"]
    print("token", token[:60], "balance", data["credits"])
else:
    print(r.status_code, data["data"]["message"])

Turnstile errors

Failed requests are never charged.

Status Message Cause Retry?
400 Missing required fields: url, site_key url or site_key is missing No, fix the request
400 invalid type, expected turnstile type is missing or not "turnstile" No, fix the request
400 Invalid URL format The URL is malformed No, send a full URL with its scheme
400 invalid proxy scheme The proxy is not http, https or socks5 No, fix the proxy
400 invalid request: check url, site_key and proxy A field was rejected No, fix the request
400 Cloudflare rejected site_key for this url The sitekey does not belong to that page No, check both values
401 invalid API key Authentication failed No, check your API key
402 insufficient credits Balance below the Turnstile price After topping up
403 this sitekey/action is not supported This sitekey or action is blocked No
429 solver busy, please retry The solver is at capacity Yes, after the Retry-After header
429 queue full, reduce thread count Too many of your requests at once Yes, with lower concurrency
500 failed to get token, please try again The solve failed, or Cloudflare or the proxy was unreachable Yes, with backoff

Turnstile best practices

  1. Use the exact page URL. Cloudflare checks the sitekey against the page it was issued for, so send the page the widget is on, not the home page.
  2. Pass action and cdata whenever the widget sets data-action or data-cdata.
  3. Solve just in time. A token lasts about five minutes and validates once.
  4. Do not retry a 400. The same request fails the same way; fix it first.

TLS Bypass

HTTP requests with a real browser's TLS fingerprint

Make HTTP requests with a real browser's TLS fingerprint to get past bot protection. You send the target URL and request details; the request goes out with the fingerprint you choose, and you get back the target's status, headers and body.

Endpoint

POST __BASE__/tls

Authentication

Requires the X-API-Key header with your API key. The other forms under Authentication work too.

Request parameters

Parameter Type Required Description
url string Yes The target URL to make the request to: http or https, query string included, up to 8,192 characters.
method string Yes HTTP method: GET, POST, PUT, PATCH, DELETE, HEAD or OPTIONS.
tls_config string No TLS configuration: CLOUDFLARE, AKAMAI or CUSTOM (default: CUSTOM).
headers object No Custom HTTP headers to include in the request, as pairs of name and string value. Up to 100 headers.
body string No Request body for POST/PUT requests, up to 1 MB. Set its Content-Type in headers. Above 64 KB, send your key in a header rather than in the body.
timeout number No Request timeout in seconds, from 1 to 120 (default: 30).

TLS configuration options

ValueUse it for
CLOUDFLAREMimics a TLS fingerprint that Cloudflare accepts. Best for sites behind Cloudflare protection.
AKAMAIMimics a TLS fingerprint tuned for Akamai. Use it for endpoints behind Akamai.
CUSTOMOur own general browser fingerprint. Works for most other sites.

Example requests

Basic GET request

cURL
curl -X POST "__BASE__/tls" \
  -H "X-API-Key: ar_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://api.example.com/data",
    "method": "GET",
    "tls_config": "CUSTOM"
  }'

POST request with headers

cURL
curl -X POST "__BASE__/tls" \
  -H "X-API-Key: ar_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://api.example.com/submit",
    "method": "POST",
    "tls_config": "CLOUDFLARE",
    "headers": {
      "Content-Type": "application/json",
      "User-Agent": "Custom-Agent/1.0"
    },
    "body": "{\"data\": \"value\"}"
  }'

With Cloudflare protection

cURL
curl -X POST "__BASE__/tls" \
  -H "X-API-Key: ar_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://protected-site.com/api",
    "method": "GET",
    "tls_config": "CLOUDFLARE"
  }'

Response format

A completed request answers 200:

Success response
{
  "status": true,
  "msg": "Success",
  "data": {
    "response": {
      "status": true,
      "status_code": 200,
      "text": "Response body content",
      "headers": {
        "content-type": "application/json",
        "server": "nginx"
      },
      "tls": {
        "ja3": "771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,0-23-65281-10-11-35-16-5-13-18-51-45-43-27-17513,29-23-24,0",
        "ja3_hash": "e7d705a3286e19ea42f587b344ee6865",
        "akamai": "1:65536,2:0,3:1000,4:6291456,6:262144|15663105|0|m,a,s,p",
        "akamai_hash": "90224459f8bf70b7d0a8797eb916dbc9"
      }
    }
  }
}

A failure answers with the HTTP status listed under Error codes:

Error response
{
  "status": false,
  "msg": "Target timed out",
  "error": "TIMEOUT"
}
FieldDescription
statustrue when the request was made, false on an error.
msgSuccess, or what went wrong.
errorOn an error, its code. Branch on this, not on msg.
data.response.status_codeThe HTTP status the target answered with.
data.response.textThe target's response body as text. Parse it yourself when it is JSON.
data.response.headersThe target's response headers. A header sent more than once, such as set-cookie, is a list.
data.response.tlsThe fingerprint the request presented. See TLS fingerprint details.
Our success is not the target's success

"status": true means the request was made and the target answered. Read data.response.status_code to see what it answered: a 403 from the target still arrives inside a 200 from us.

Error codes

Error code Status msg Description
INVALID_URL 400 Invalid URL format The provided URL is malformed or invalid
TIMEOUT 504 Target timed out Request exceeded the timeout limit
CONNECTION_ERROR 502 Target connection failed Failed to establish connection to target
TLS_ERROR 502 Target TLS handshake failed TLS handshake failed. Try another tls_config
RATE_LIMIT 429 Service Overloaded Too many requests, please slow down. Wait for Retry-After
INSUFFICIENT_CREDITS 402 Insufficient credits Not enough balance in your account
INVALID_API_KEY 401 Invalid API key The API key is missing or wrong
INVALID_REQUEST 400 Missing required fields url is missing, or the body is not valid JSON
400 Invalid method method is not one of the supported verbs
400 Invalid tls_config tls_config is not CLOUDFLARE, AKAMAI or CUSTOM
400 Invalid headers Not an object of strings, over 100 headers, or a value with a line break
400 Invalid body body is not text or JSON, or is over 1 MB
400 Invalid timeout timeout is not a number from 1 to 120
413 Request body too large The JSON you sent is over the size limit
RESPONSE_TOO_LARGE 502 Response too large The target sent back more than 16 MB
SERVICE_UNAVAILABLE 503 Service temporarily at capacity At capacity or in maintenance. Retry shortly
REQUEST_FAILED 500 Request failed The request could not be completed. Retry with backoff

TLS fingerprint details

Every successful response includes the fingerprint the request presented, in data.response.tls:

  • JA3 hash (ja3_hash): the client TLS fingerprint identifier.
  • Akamai hash (akamai_hash): the Akamai style HTTP/2 fingerprint.
  • Full JA3 string (ja3): the complete TLS parameters used. akamai is the full HTTP/2 string.

Use them to verify which TLS configuration was used and to track fingerprint consistency.

Pricing

  • $0.0007 per request ($0.70 per 1,000)
  • Billed per successful request
  • Failed requests are not charged

A request succeeds once the target returns any HTTP response, including a 4xx or 5xx, because the request was made. A timeout, a refused connection or a failed handshake costs nothing.

Best practices

  1. Choose the right config. Use CLOUDFLARE for sites behind Cloudflare and AKAMAI for Akamai protection.
  2. Handle timeouts. Set timeout to suit how long the target usually takes, and give your own HTTP client that long plus 30 seconds.
  3. Retry logic. Use exponential backoff for transient errors (RATE_LIMIT, SERVICE_UNAVAILABLE, REQUEST_FAILED). A POST, PUT, PATCH or DELETE is never sent twice on your behalf, so retry one only when repeating it is safe.
  4. Header matching. Include the headers the target site expects, such as a User-Agent that fits the chosen config.

Code examples

import requests

API_KEY = "ar_live_YOUR_KEY"
headers = {"X-API-Key": API_KEY, "Content-Type": "application/json"}
payload = {
    "url": "https://httpbin.org/get",
    "method": "GET",
    "tls_config": "CUSTOM"
}

response = requests.post(
    "__BASE__/tls",
    headers=headers,
    json=payload,
    timeout=60
)
data = response.json()

if data.get("status"):
    print("Success!")
    print("Response:", data["data"]["response"]["text"])
    print("JA3 Hash:", data["data"]["response"]["tls"]["ja3_hash"])
else:
    print("Error:", data.get("error"), data.get("msg"))

Check your balance

GET __BASE__/balance

Returns your balance in dollars and what it still covers on each endpoint. POST works too. This call is free and does not count against your rate limit budget in any meaningful way. credits is the number of reCAPTCHA v3 solves left, as it always was; remaining gives the same count for every endpoint.

Example
curl __BASE__/balance -H "X-API-Key: ar_live_YOUR_KEY"

{
  "status": "success",
  "credits": 998,
  "balance_usd": 1.996,
  "remaining": {
    "recaptcha_v3": 998,
    "turnstile": 2851,
    "tls": 2851
  }
}

Your dashboard

Sign in at /dashboard with any of your API keys to see your account in one place: your balance and what it covers on each product, usage over the last 24 hours and 30 days, requests per day, your keys, your limits, your recent requests with the result each one returned, and your top ups.

  • The dashboard is read only. Nothing there changes your account or spends balance.
  • Target sites are masked, for example https://ex***.com/***: the path, query and most of the host are never sent to your browser, so a token in a URL cannot leak from a shared screen.
  • For TLS Bypass, each request shows the status the target answered, such as Target 403, next to our own result.
  • Your key is exchanged once for a session that lasts up to 12 hours, or 2 hours without activity. The key itself is not stored in your browser.
  • The session belongs to the key you signed in with: if that key is replaced or switched off, the session ends at once.
  • Signing in is not an API request and is never charged.

Service status

GET __BASE__/health

No authentication required. Returns "maintenance" as the status while the service is paused. Requests then answer 503 (SERVICE_UNAVAILABLE on /tls), and Turnstile answers 429 solver busy, please retry.

Example
{
  "status": "success",
  "service": "Aries Solver"
}

Common errors

A reCAPTCHA v3 failure returns {"status": "error", "message": "…"} with one of the messages below. The HTTP status and the message together tell you whether to fix the request, top up, or retry. Turnstile and TLS have their own formats, listed under Turnstile errors and TLS error codes.

Status Message Cause Solution
400 Missing required fields A required field such as url is empty Provide all required fields
400 Invalid URL format Malformed URL Use a full URL with scheme
400 Invalid sitekey format Site key is not a plausible key Copy the key from the target page
400 Missing required field: proxy No proxy provided Provide a valid proxy
400 Invalid proxy format Malformed proxy URL Check the proxy format
400 Bad proxy Proxy not working Use a different proxy
400 Invalid action reCAPTCHA action is longer than 64 characters Send the action the page uses
401 Invalid API key Authentication failed Check your API key
402 Insufficient credits Balance below this endpoint's price Top up
413 Request body too large The JSON you sent is over the size limit Send a smaller request
429 Service Overloaded Concurrency or rate limit hit Retry after a moment
500 Error fetching token A captcha solve failed Retry with backoff
503 Service temporarily at capacity All solvers busy, or maintenance Retry shortly
Which errors are worth retrying

Retry 429, 500 and 503 with exponential backoff. Every 400, 401 and 403 will fail again unchanged, so fix the request instead. 402 means top up. A 502 or 504 from /tls describes the target, so retry only if repeating that request is safe.

Rate limits

Each account has a ceiling on requests per minute and a cap on requests running at once, shared across every endpoint. Both are set per account and can be raised: ask on Telegram if you are hitting them.

HeaderMeaning
X-RateLimit-LimitRequests allowed per minute.
X-RateLimit-RemainingRequests left in the current minute.
X-RateLimit-ResetSeconds until the window resets.
Retry-AfterSent with 429. Wait this many seconds.

Exceeding either limit returns 429 with Service Overloaded (error code RATE_LIMIT on /tls), or on /solve with solver busy, please retry for the limit per minute and queue full, reduce thread count for the cap on requests at once. Honour Retry-After rather than retrying immediately.

Best practices

  • Solve just in time. Tokens last about two minutes, so request one when you are ready to use it.
  • Send the fingerprint back. The user agent, client hints and language in the response are part of the solve.
  • Reuse the same proxy. Solve and submit from the same exit address.
  • Pass the right action. Scores often depend on it matching the page.
  • Back off on 429 and 5xx. Double the wait each attempt rather than retrying in a tight loop.
  • Watch your balance. Read balance_usd from each reCAPTCHA response and credits from each Turnstile response instead of polling /balance.
  • Set a generous client timeout. Allow at least 180 seconds; a solve can take a while under load. For /tls, allow your timeout plus 30 seconds.
  • Know what gets resent. A /tls request with POST, PUT, PATCH or DELETE is never sent twice on your behalf. GET, HEAD and OPTIONS may be retried automatically after a failure on our side.

Topping up

You top up one balance in dollars, and it never expires. It is spent at each endpoint's own price: reCAPTCHA v3 at $2.00 per 1,000 solves, Turnstile at $0.70 per 1,000 solves and TLS at $0.70 per 1,000 requests. Keys are issued by hand, so message us with the volume you expect and one will be created for you.

https://t.me/Anxioussoul