Captcha OCR

SDKs / Rust

Rust SDK

Package captcha-ocr, version 1.0.0. Requires Rust 1.88+ (async, reqwest; runs on tokio).

Install

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

# 1. Add our registry once, in .cargo/config.toml (project) or ~/.cargo/config.toml
[registries.allvoraz]
index = "sparse+https://captchaocr.allvoraz.com/sdk/cargo/index/"

# 2. Add the crate (and an async runtime)
cargo add captcha-ocr --registry allvoraz
cargo add tokio --features full

# Cargo.toml gets:
#   captcha-ocr = { version = "1.0.0", registry = "allvoraz" }

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.

use base64::{engine::general_purpose::STANDARD, Engine as _};
use captcha_ocr::apis::{configuration::Configuration, solve_api};
use captcha_ocr::models::SolveRequest;

let mut config = Configuration::new();
config.base_path = "https://captchaocr.allvoraz.com".into();
config.bearer_access_token = Some(std::env::var("CAPTCHA_API_KEY")?);

let mut req = SolveRequest::new(STANDARD.encode(std::fs::read("captcha.png")?));
req.numeric = Some(true);
req.length = Some(Some(6)); // nullable fields are Option<Option<T>>

let res = solve_api::solve(&config, req).await?;
if res.reliable == Some(true) {
    println!("{}", res.text.unwrap_or_default()); // only reliable answers are 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.

use captcha_ocr::models::{BatchItem, BatchRequest};

let a = BatchItem::new(b64("a.png"));
let mut b = BatchItem::new(b64("b.png"));
b.length = Some(Some(5)); // per-image override
let mut sum = BatchItem::new(b64("sum.png"));
sum.math = Some(Some(true));

let mut req = BatchRequest::new(vec![a, b, sum]);
req.numeric = Some(true); // shared by every image

let batch = solve_api::solve_batch(&config, req).await?;
for r in batch.results { // same order as the request
    println!("{:?} reliable={:?}", r.text, r.reliable);
}

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.

use captcha_ocr::models::task_result::Status;

// Submit: returns a task id at once, the captcha is solved in the background.
let task = solve_api::submit(&config, req).await?;

// ... do other work ...

let r = solve_api::get_result(&config, task.id, Some(10)).await?; // waits up to 10 s
if let (Status::Ready, Some(Some(res))) = (r.status, &r.result) {
    println!("{}", res.text.clone().unwrap_or_default());
}

Or poll without holding the connection:

// Poll without holding the connection.
let mut r = solve_api::get_result(&config, task.id, None).await?;
while r.status == Status::Processing {
    tokio::time::sleep(std::time::Duration::from_millis(500)).await;
    r = solve_api::get_result(&config, task.id, None).await?;
}

Balance

let credits = captcha_ocr::apis::account_api::balance(&config).await?.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.

use captcha_ocr::apis::account_api;
use captcha_ocr::models::AlertRequest;
use std::collections::HashMap;

println!("{}", account_api::balance(&config).await?.credits);

// When credits drop below 500, POST this payload to your URL (one alert per account).
let mut alert = AlertRequest::new(500, "https://hooks.example.org/captcha-credits".into());
alert.payload = Some(Some(HashMap::from([("text".into(), serde_json::json!("Captcha credits low: {{credits}} left"))])));
alert.headers = Some(Some(HashMap::from([("Authorization".into(), "Bearer my-hook-secret".into())])));
account_api::set_alert(&config, alert).await?;
let test = account_api::test_alert(&config).await?; // sends it now
println!("{} {:?}", test.delivered, test.status.flatten());
// account_api::delete_alert(&config).await?;       // remove it

Report a wrong answer

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

// The site rejected the answer: get the credit back (within 48 hours).
let r = captcha_ocr::apis::account_api::report(&config,
    captcha_ocr::models::ReportRequest::new(res.id.flatten().unwrap())).await?;

Errors

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

More