Skip to content

Math CAPTCHA

Read the expression. Return its computed answer. Capture the arithmetic image for the current form and encode its bytes. The solution includes the recognized expression and computed answer.

POST /createTask · example
{
  "clientKey": "capzy_YOUR_API_KEY",
  "task": {
    "type": "MathCaptchaTask",
    "body": "/9j/4AAQSkZJRgABAQ..."
  }
}

Illustrative values. Replace the inputs with values from your current integration.

Base64 arithmetic imageDirect task integrationAnswer + recognized expression

Send the arithmetic image.

Capture the arithmetic image for the current form and encode its bytes. The solution includes the recognized expression and computed answer.

Your API key authenticates Capzy.
Provider keys, challenge IDs, images, and session values belong inside task.

Keep the question linked to the form session.

  1. Save the current arithmetic image response from Network or your existing HTTP client.
  2. Retain the challenge/form identifiers and cookies that produced it. Keep the image unmodified.
  3. Base64-encode those original bytes into body rather than passing the file path.
Input collection example - replace illustrative values
import base64
from pathlib import Path

def image_bytes(filename):
    return base64.b64encode(Path(filename).read_bytes()).decode("ascii")

task_inputs = {"body": image_bytes("arithmetic.png")}

Send the image itself; a typed expression is not the image input contract for this task.

How Math CAPTCHA works

A math captcha is an image showing a small arithmetic expression — addition, subtraction, multiplication, or division of two or three small whole numbers (e.g. '7 + 2', 'twelve minus four', '6 × 3'). The user is expected to compute the result and type the numeric answer.

Capzy's proprietary pipeline reads the expression off the image and returns the computed answer. Fast API path — no proxy, typical solves in ~0.6–1s.

  • Handles + − × ÷ with two or three operands
  • Reads symbols and word forms ('plus', 'minus')
  • No proxy needed — pure image-in answer-out
  • Typical solve under 1 second

Know what goes in.

Choose a field to see its purpose, where to get it, and its place in the request. Optional values omitted from the example can be added when your flow uses them.

The request below follows your selected task configuration.

Request authentication

Required task inputs

body

stringRequired

Base64-encoded image (PNG, JPG, GIF, BMP) of the math expression

Where it comes from

Save the original CAPTCHA image bytes from the current challenge and base64-encode them. Send the encoded bytes, not a local path.

Open the input guide
Example value/9j/4AAQSkZJRgABAQ...
POST /createTask · selected configuration
{
  "clientKey": "capzy_YOUR_API_KEY",
  "task": {
    "type": "MathCaptchaTask",
    "body": "/9j/4AAQSkZJRgABAQ..."
  }
}

The selected field is highlighted when present. Preserve the declared value type and current challenge context.

Make your first request.

Create the task, keep its taskId, and poll until status is ready. Then read the selected variant's solution.

More examples
  1. Create the task

    Send clientKey and the selected task to /createTask from your server. Keep the returned taskId.

  2. Wait for the solution

    Send that same key and ID to /getTaskResult. While processing, wait two seconds before checking again. Stop on Ready or an error.

  3. Apply the result

    Use solution.text as the arithmetic answer and inspect solution.expression when diagnosing an unexpected result. Submit with the form that issued that image.

solve_math_captcha.py
import json, os, time
import requests

API = "https://api.capzy.ai"
KEY = os.environ["CAPZY_API_KEY"]
task = json.loads("{\"type\":\"MathCaptchaTask\",\"body\":\"/9j/4AAQSkZJRgABAQ...\"}")

def call(path, payload):
    response = requests.post(f"{API}/{path}", json={"clientKey": KEY, **payload}, timeout=30)
    response.raise_for_status()
    data = response.json()
    if data.get("errorId", 0) or data.get("status") == "failed":
        raise RuntimeError(data.get("errorDescription") or data.get("errorCode") or "Task failed")
    return data

created = call("createTask", {"task": task})
for attempt in range(60):
    result = call("getTaskResult", {"taskId": created["taskId"]})
    if result.get("status") == "ready":
        solution = result["solution"]
        print(solution)
        break
    time.sleep(2)
else:
    raise TimeoutError("Task is still processing; keep the taskId to check it later.")

Before runningReplace all illustrative inputs with your captured values. Set CAPZY_API_KEY in your environment. Install requests with pip install requests.

Polling and failuresThe example checks HTTP/API failures, uses 30-second request timeouts, and stops after 60 result checks. Retain taskId if your task is still processing.

Understand what comes back.

Follow this task from creation to completion. Response fields and usage follow your selected request variant.

Answer + recognized expression

Use solution.text as the arithmetic answer and inspect solution.expression when diagnosing an unexpected result. Submit with the form that issued that image.

string
The computed numeric answer (e.g. '8')
string
The expression we read from the image, in standard form (e.g. '3 + 5')
POST /getTaskResult · example response
{
  "errorId": 0,
  "status": "ready",
  "solution": {
    "text": "8",
    "expression": "3 + 5"
  }
}

Illustrative values. Additional metadata may be returned; only Ready contains a completed solution.

Use the result

Use solution.text as the arithmetic answer and inspect solution.expression when diagnosing an unexpected result. Submit with the form that issued that image.

Execution context result is the parsed Ready response from the polling example. session, when referenced, is your existing requests.Session (or browser-compatible session) with the original cookie jar, headers, and solving proxy configured in session.proxies for both http and https. Keep this client for the complete flow. task is the task object you submitted. For Shape, action_body is the original protected request body as bytes or a string, with its original Content-Type in session.headers. Install curl_cffi when the fragment imports it; match the target's required browser/TLS identity.

Use the result · Python

# Step 3: Image-to-text / math — submit the recognized text as the captcha answer
answer = result["solution"]["text"]
requests.post("https://target.example.com/login", data={"username": "...", "captcha": answer})

When something doesn't work.

Check your captured values, the selected variant, and the response before starting another task.

What kind of expressions does it handle?

Simple arithmetic with two or three small whole numbers — addition, subtraction, multiplication, and integer division. Both symbol forms ('3 + 5') and word forms ('three plus five') are supported.

Why is this separate from Image to Text?

Image to Text returns the literal characters it sees. Math Captcha returns the computed answer the site expects you to submit, plus the expression we read so you can audit wrong answers.

What if the answer isn't a whole number?

Math captchas in the wild always evaluate to a whole number. If we read an expression that doesn't evaluate cleanly we return ERROR_CAPTCHA_UNSOLVABLE rather than guess.

Connect Math CAPTCHA to your workflow.

Get your Capzy API key and use this guide's integration.

$0.80Per 1,000 solves
0.9sAverage solve time

MathCaptchaTask · Live configuration