Skip to content

ALTCHA

Solve the issued proof-of-work challenge. Use the signed challenge document issued by your ALTCHA integration. You can send its complete JSON object or its challenge endpoint URL.

POST /createTask · example
{
  "clientKey": "capzy_YOUR_API_KEY",
  "task": {
    "type": "AltchaTaskProxyLess",
    "challenge": {
      "algorithm": "SHA-256",
      "challenge": "6abc3434b5ac6b2e509ee5aeae81b43b4ee80902850a3f3b52a2734478c9eee2",
      "maxnumber": 50000,
      "salt": "5206b8e45d88a37fc4e0247e",
      "signature": "3debf2d432ec072ba6cc573581d24d77118f0230c2c3a3dc1e35725c5af7b879"
    }
  }
}

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

Challenge object or challenge URLProxyless or your own proxyALTCHA token + payload

Capture the issued challenge.

Use the signed challenge document issued by your ALTCHA integration. You can send its complete JSON object or its challenge endpoint URL.

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

Preserve the signed document unchanged.

  1. Inspect the widget's challenge configuration or the Network request that fetches its current challenge JSON.
  2. Copy the complete response object into task.challenge, preserving algorithm, challenge, salt, signature, maxnumber, and any additional original fields.
  3. Prefer this inline object when the challenge endpoint needs your browser/session context.
Input collection example - replace illustrative values
{
  "challenge": {
    "algorithm": "SHA-256",
    "challenge": "YOUR_ISSUED_HASH",
    "maxnumber": 50000,
    "salt": "YOUR_ISSUED_SALT",
    "signature": "YOUR_ISSUED_SIGNATURE"
  }
}

These illustrated values cannot form a valid signed challenge. Copy the actual document your application issued.

Provider integration documentation
How ALTCHA works

ALTCHA is an open-source, self-hostable proof-of-work captcha with no tracking and no puzzles. The server issues a challenge — {algorithm, challenge, salt, maxnumber, signature} — and the browser brute-forces the integer N whose hash matches. It's used by privacy-conscious sites that don't want to send data to Google or hCaptcha.

We run the same hash search the widget would — SHA-256 (default), plus SHA-384, SHA-512, and SHA-1 — in parallel across cores, and return the base64-encoded solution payload in the exact format the ALTCHA widget submits. Pass the challenge object, or a challengeURL we fetch (on AltchaTask, THROUGH your proxy with coherent browser headers, so managed ALTCHA/Sentinel endpoints that gate datacenter IPs still return a challenge), and get the token in milliseconds.

  • Solves SHA-256 / SHA-384 / SHA-512 / SHA-1 proof-of-work in milliseconds
  • Multi-core parallel search — trivial to tough challenges alike
  • Output matches the official ALTCHA widget payload exactly
  • Proxyless pure-compute, or fetch the challengeURL through your proxy (AltchaTask) to clear IP-gated endpoints

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

Optional context

type

stringRequired

The exact API identifier for the selected task variant and network mode.

Where it comes from

Choose the task/network or request variant on this page. The integration examples update this exact API task identifier.

Open the input guide
Example valueAltchaTaskProxyLess
POST /createTask · selected configuration
{
  "clientKey": "capzy_YOUR_API_KEY",
  "task": {
    "type": "AltchaTaskProxyLess",
    "challenge": {
      "algorithm": "SHA-256",
      "challenge": "6abc3434b5ac6b2e509ee5aeae81b43b4ee80902850a3f3b52a2734478c9eee2",
      "maxnumber": 50000,
      "salt": "5206b8e45d88a37fc4e0247e",
      "signature": "3debf2d432ec072ba6cc573581d24d77118f0230c2c3a3dc1e35725c5af7b879"
    }
  }
}

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 the encoded solution.token in the widget's configured form field, commonly altcha. Preserve the returned payload for integrations that consume its structured fields and validate against the issued challenge on your backend.

solve_altcha.py
import json, os, time
import requests

API = "https://api.capzy.ai"
KEY = os.environ["CAPZY_API_KEY"]
task = json.loads("{\"type\":\"AltchaTaskProxyLess\",\"challenge\":{\"algorithm\":\"SHA-256\",\"challenge\":\"6abc3434b5ac6b2e509ee5aeae81b43b4ee80902850a3f3b52a2734478c9eee2\",\"maxnumber\":50000,\"salt\":\"5206b8e45d88a37fc4e0247e\",\"signature\":\"3debf2d432ec072ba6cc573581d24d77118f0230c2c3a3dc1e35725c5af7b879\"}}")

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.

ALTCHA token + payload

Use the encoded solution.token in the widget's configured form field, commonly altcha. Preserve the returned payload for integrations that consume its structured fields and validate against the issued challenge on your backend.

string
Base64-encoded solution payload — set it as the altcha-payload / altcha form field value (matches the official widget output), then submit
object
The decoded solution {algorithm, challenge, number, salt, signature, took} for inspection
POST /getTaskResult · example response
{
  "errorId": 0,
  "status": "ready",
  "solution": {
    "token": "eyJhbGdvcml0aG0iOiJTSEEtMjU2IiwiY2hhbGxlbmdlIjoiMDAwMDAwZjJhNDU2Nzg5MCIsIm51bWJlciI6NjU0MzIxLCJzYWx0IjoidGVzdF9zYWx0Iiwic2lnbmF0dXJlIjoiIiwidG9vayI6MjV9",
    "payload": {
      "algorithm": "SHA-256",
      "challenge": "000000f2a4567890",
      "number": 654321,
      "salt": "test_salt",
      "signature": "",
      "took": 25
    }
  }
}

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

Submit the encoded ALTCHA proof

The default widget field is altcha; match any custom name setting. Send solution.token, the encoded proof, rather than the decoded solution.payload object. Validate it on your backend against the challenge that issued it.

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
token = result["solution"]["token"]
# Keep the original form's action, other fields, and session.
response = session.post("https://target.example.com/submit", data={
    "altcha": token,
    # Add the original application form fields here.
}, timeout=30)

When something doesn't work.

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

How do I use the token?

Set the returned token as the value of the ALTCHA form field (the hidden input the widget populates, usually named 'altcha' or 'altcha-payload'), then submit. Your server verifies it against the same salt/signature it issued.

Do I send the challenge or a URL?

Prefer the challenge object. If you already have the challenge JSON from your page, send the whole thing as 'challenge' — that's the reliable path. Only use challengeURL when that endpoint is publicly fetchable server-side; if it's behind a JS/WAF anti-bot we can't reach it. One of the two is required.

My task fails with 'challenge and salt are required' or ERROR_INVALID_PARAMS. Why?

You're passing the fields the wrong way. Send the FULL nested object: challenge: {algorithm, challenge, salt, maxnumber, signature}. Sending salt/signature/iterations as top-level task fields, or challenge:null, won't work — the 'challenge' hash is the target we solve for and it must be inside the challenge object. Note some widgets call maxnumber 'iterations'; pass its value as maxnumber.

The challengeURL times out or returns something odd.

Some deployments put the challenge endpoint behind a JS/WAF anti-bot, so a server-side GET never receives a real challenge (you'll see a stub or a block, not {algorithm, challenge, salt, ...}). Capture the challenge object in your browser — which already passed the gate — and pass it inline via 'challenge' instead of pointing us at the URL.

Connect ALTCHA to your workflow.

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

$1.00Per 1,000 solves
1.8sAverage solve time

AltchaTaskProxyLess · Live configuration