Captcha OCR

SDKs / Python

Python SDK

Package captcha-ocr-client, version 1.0.0. Requires Python 3.9+.

Install

The SDK installs straight from our package server, captchaocr.allvoraz.com/sdk, with your usual tools. No public registry account is needed.

# pip
pip install https://captchaocr.allvoraz.com/sdk/python/captcha_ocr_client-1.0.0-py3-none-any.whl

# requirements.txt
captcha-ocr-client @ https://captchaocr.allvoraz.com/sdk/python/captcha_ocr_client-1.0.0-py3-none-any.whl

# Poetry / uv
poetry add https://captchaocr.allvoraz.com/sdk/python/captcha_ocr_client-1.0.0-py3-none-any.whl
uv add https://captchaocr.allvoraz.com/sdk/python/captcha_ocr_client-1.0.0-py3-none-any.whl

# then: import captcha_ocr

Prefer the code itself? Download the source (.zip).

Configure and solve

Create the client once with your API key (from Dashboard → API keys) and reuse it. Submit the answer only when reliable is true. Only reliable answers are charged.

import base64, os
import captcha_ocr
from captcha_ocr import SolveRequest

config = captcha_ocr.Configuration(
    host="https://captchaocr.allvoraz.com",
    access_token=os.environ["CAPTCHA_API_KEY"],
)
client = captcha_ocr.ApiClient(config)          # reuse it: keeps connections open
solver = captcha_ocr.SolveApi(client)

image = base64.b64encode(open("captcha.png", "rb").read()).decode()
res = solver.solve(SolveRequest(image=image, numeric=True, length=6))
if res.reliable:
    print(res.text)          # submit it (1 credit)
else:
    print("refresh the captcha")  # not charged

Options: numeric, uppercase, lowercase, length, math, hindi. See choosing options.

Batch

Up to 256 images in one call. Top-level options are shared, and each item can override them. Results keep the request order.

import base64
import captcha_ocr
from captcha_ocr import BatchItem, BatchRequest

def b64(path):
    return base64.b64encode(open(path, "rb").read()).decode()

config = captcha_ocr.Configuration(host="http://localhost:8080")
with captcha_ocr.ApiClient(config) as client:
    batch = captcha_ocr.SolveApi(client).solve_batch(BatchRequest(
        numeric=True,                                      # shared by every image
        images=[
            BatchItem(image=b64("a.png")),
            BatchItem(image=b64("b.png"), length=5),       # per-image override
            BatchItem(image=b64("sum.png"), math=True),
        ],
    ))
    for r in batch.results:                                # same order as the request
        print(r.text if r.reliable else f"refresh ({r.error or 'unsure'})")

Submit now, fetch later

submit returns a task id immediately and solves in the background. getResult returns processing, then ready with the same answer solve returns (or failed, credit returned). Pass wait (up to 30 s) to hold the call until it's ready.

# Submit: returns a task id at once, the captcha is solved in the background.
task = solver.submit(SolveRequest(image=image, numeric=True, length=6))

# ... do other work ...

r = solver.get_result(task.id, wait=10)  # waits up to 10 s for the answer
if r.status == "ready" and r.result.reliable:
    print(r.result.text)

Or poll without holding the connection:

import time

# Poll without holding the connection.
while (r := solver.get_result(task.id)).status == "processing":
    time.sleep(0.5)
print(r.status, r.result.text if r.result else r.error)

Balance

account = captcha_ocr.AccountApi(client)
print(account.balance().credits)

Low-balance alert

One alert per account: when a solve leaves your credits below threshold, the service POSTs your payload to your HTTPS url. It fires once and re-arms when you add credits. testAlert sends it now; getAlert and deleteAlert read and remove it. See how alerts work.

from captcha_ocr import AlertRequest

account = captcha_ocr.AccountApi(client)
print(account.balance().credits)

# When credits drop below 500, POST this payload to your URL (one alert per account).
account.set_alert(AlertRequest(
    threshold=500,
    url="https://hooks.example.org/captcha-credits",
    payload={"text": "Captcha credits low: {{credits}} left"},
    headers={"Authorization": "Bearer my-hook-secret"},
))
print(account.test_alert())   # sends it now: delivered=True status=200
# account.delete_alert()      # remove it

Report a wrong answer

If the site rejected a reliable answer, report its id within 48 hours to get the credit back.

from captcha_ocr import ReportRequest

# The site rejected res.text: get the credit back (within 48 hours).
r = captcha_ocr.AccountApi(client).report(ReportRequest(id=res.id))
print(r.refunded, r.reason)

Errors

HTTP errors (401 bad key, 402 no credits, 404 unknown task, 422 invalid options, 429 too many concurrent requests, 503 retry later) raise captcha_ocr.exceptions.ApiException (status, body). An undecodable image is not an exception: it's a normal result with error: "invalid_image". See errors.

More