Skip to main content

Altcha Solver

CI PyPI version Python 3.6+ License: MIT

Universal proof-of-work CAPTCHA solver for Altcha - supports ALL algorithm variants.

Altcha is an open-source, privacy-focused CAPTCHA alternative that uses proof-of-work (PoW) instead of image recognition. This solver implements all 8 supported algorithms, allowing you to solve any Altcha challenge programmatically.


Table of Contents


Features

  • Universal Compatibility: Supports all 8 Altcha algorithm variants
  • Zero Dependencies: Core functionality uses Python standard library only
  • Battle-Tested: Validated against official Altcha Playground
  • Production Ready: Includes parallel processing, verification, and payload encoding
  • Well Documented: Complete algorithm specifications and examples

Supported Algorithms

Algorithm Type Python Support Description
SHA-256 Hash Native Simple hash matching
SHA-384 Hash Native 384-bit hash matching
SHA-512 Hash Native 512-bit hash matching
PBKDF2/SHA-256 KDF Native Key derivation, 256-bit
PBKDF2/SHA-384 KDF Native Key derivation, 384-bit
PBKDF2/SHA-512 KDF Native Key derivation, 512-bit
Scrypt Memory-hard Native (3.6+) Memory-hard KDF
Argon2id Memory-hard Requires argon2-cffi Modern memory-hard KDF

Installation

From PyPI (Recommended)

pip install altcha-solver

# With Argon2 support
pip install altcha-solver[argon2]

From Source

git clone https://github.com/opastorello/altcha-solver.git
cd altcha-solver
pip install .

# Or install in development mode
pip install -e .[dev]

Requirements: Python 3.6+


Quick Start

from altcha_solver import AltchaSolver

# Create solver
solver = AltchaSolver()

# Solve any Altcha challenge
challenge = {
    "parameters": {
        "algorithm": "PBKDF2/SHA-256",
        "nonce": "4db2e1ee6108476cba8972f39cf900b9",
        "salt": "98b95a514955c35e73de9252423882a5",
        "cost": 5000,
        "keyLength": 32,
        "keyPrefix": "00"
    }
}

solution = solver.solve(challenge)
print(f"Counter: {solution['counter']}")
print(f"Key: {solution['derivedKey']}")

# Build submission payload
payload = solver.build_payload(challenge, solution)

Usage

Python Library

from altcha_solver import AltchaSolver

solver = AltchaSolver(max_iterations=100000)

# Automatic algorithm detection
solution = solver.solve(challenge)

# Verify solution
is_valid = solver.verify_solution(challenge["parameters"], solution)

# Build base64 payload for submission
payload = solver.build_payload(challenge, solution)

# List supported algorithms
algorithms = solver.list_algorithms()

Command Line

# PBKDF2/SHA-256
python altcha_solver.py pbkdf2 \
    --nonce "4db2e1ee6108476cba8972f39cf900b9" \
    --salt "98b95a514955c35e73de9252423882a5" \
    --cost 5000 --prefix "00"

# PBKDF2/SHA-384
python altcha_solver.py pbkdf2-384 \
    --nonce "4db2e1ee6108476cba8972f39cf900b9" \
    --salt "98b95a514955c35e73de9252423882a5" \
    --cost 5000 --prefix "00"

# Scrypt
python altcha_solver.py scrypt \
    --nonce "4db2e1ee6108476cba8972f39cf900b9" \
    --salt "98b95a514955c35e73de9252423882a5" \
    --cost 16384 --prefix "00"

# Argon2id (requires argon2-cffi)
python altcha_solver.py argon2 \
    --nonce "4db2e1ee6108476cba8972f39cf900b9" \
    --salt "98b95a514955c35e73de9252423882a5" \
    --cost 3 --memory 65536 --prefix "00"

# SHA-256 (legacy mode)
python altcha_solver.py sha256 \
    --salt "randomsalt" \
    --challenge "expected_hash_here"

# JSON output
python altcha_solver.py pbkdf2 --nonce ... --output json

# List algorithms
python altcha_solver.py --list

Algorithm Reference

PBKDF2 Variants

The most common Altcha implementation. Uses Password-Based Key Derivation Function 2.

Challenge Structure:

{
  "parameters": {
    "algorithm": "PBKDF2/SHA-256",
    "nonce": "4db2e1ee6108476cba8972f39cf900b9",
    "salt": "98b95a514955c35e73de9252423882a5",
    "cost": 5000,
    "keyLength": 32,
    "keyPrefix": "0051627a347a5c8a",
    "memoryCost": 0
  },
  "signature": "7b2de5af..."
}

Parameters:

Parameter Type Description
algorithm string PBKDF2/SHA-256, PBKDF2/SHA-384, or PBKDF2/SHA-512
nonce hex string 16 random bytes (32 hex chars)
salt hex string 16 random bytes (32 hex chars)
cost integer PBKDF2 iterations (typically 2000-10000)
keyLength integer Output key size in bytes (32, 48, or 64)
keyPrefix hex string Required prefix of derived key
signature hex string HMAC for server verification

Algorithm:

FOR counter FROM 0 TO MAX:
    password = nonce_bytes (16B) + counter_bytes (4B big-endian)
    key = PBKDF2-HMAC-SHA256(password, salt_bytes, cost, keyLength)
    IF key.hex().startswith(keyPrefix):
        RETURN {counter, key}

SHA Variants

Legacy format using simple hash matching.

Mode 1: Challenge Matching

hash = SHA256(salt_string + counter_string)
valid if hash == challenge

Mode 2: Prefix Matching

hash = SHA256(nonce_bytes + counter_bytes)
valid if hash.hex().startswith(keyPrefix)

Scrypt

Memory-hard key derivation function. Native in Python 3.6+.

Parameters:

Parameter Description Typical Value
cost N parameter (CPU/memory) 16384
memoryCost r parameter (block size) 8
parallelism p parameter 1

Algorithm:

password = nonce_bytes + counter_bytes
key = scrypt(password, salt, N=cost, r=memoryCost, p=parallelism)
valid if key.hex().startswith(keyPrefix)

Argon2id

Modern memory-hard KDF. Requires argon2-cffi package.

Parameters:

Parameter Description Typical Value
cost Time cost (iterations) 3
memoryCost Memory in KB 65536
parallelism Parallel threads 1

Algorithm:

password = nonce_bytes + counter_bytes
key = argon2id(password, salt, time=cost, memory=memoryCost, parallelism)
valid if key.hex().startswith(keyPrefix)

API Reference

AltchaSolver

class AltchaSolver:
    def __init__(self, max_iterations: int = 100000):
        """Initialize solver with maximum iteration limit."""

    def solve(self, challenge: dict) -> dict:
        """
        Solve any Altcha challenge.

        Args:
            challenge: Challenge dict with 'parameters' key

        Returns:
            Solution dict with 'counter', 'derivedKey'/'hash', 'time'

        Raises:
            ValueError: Unsupported algorithm
            RuntimeError: No solution found
        """

    def verify_solution(self, params: dict, solution: dict) -> bool:
        """Verify a solution is correct."""

    def build_payload(self, challenge: dict, solution: dict) -> str:
        """Build base64-encoded submission payload."""

    @staticmethod
    def list_algorithms() -> list:
        """Return list of supported algorithm names."""

Solution Format

{
    "counter": 491,           # Found counter value
    "derivedKey": "001a40..", # Derived key (PBKDF2/Scrypt/Argon2)
    "hash": "abc123...",      # Hash (SHA variants)
    "time": 1494.4            # Solving time in milliseconds
}

Payload Format

The submission payload is base64-encoded JSON:

{
  "challenge": { /* original challenge */ },
  "solution": {
    "counter": 491,
    "derivedKey": "001a40bc...",
    "time": 1494.4
  }
}

Examples

Example 1: Basic PBKDF2

from altcha_solver import AltchaSolver

solver = AltchaSolver()

# Challenge from Altcha Playground
challenge = {
    "parameters": {
        "algorithm": "PBKDF2/SHA-256",
        "nonce": "4db2e1ee6108476cba8972f39cf900b9",
        "salt": "98b95a514955c35e73de9252423882a5",
        "cost": 5000,
        "keyLength": 32,
        "keyPrefix": "00"
    }
}

solution = solver.solve(challenge)
# Output: counter=491, derivedKey=001a40bc...

Example 2: Parallel Batch Processing

from concurrent.futures import ThreadPoolExecutor
from altcha_solver import AltchaSolver

def solve_one(challenge):
    return AltchaSolver().solve(challenge)

# Pre-fetch challenges from server
challenges = [fetch_challenge() for _ in range(100)]

# Solve in parallel
with ThreadPoolExecutor(max_workers=20) as executor:
    solutions = list(executor.map(solve_one, challenges))

# 100 solved captchas ready to use

Example 3: Full HTTP Flow

import requests
from altcha_solver import AltchaSolver

# 1. Get challenge
response = requests.get("https://example.com/api/captcha")
challenge = response.json()

# 2. Solve
solver = AltchaSolver()
solution = solver.solve(challenge)

# 3. Build payload
payload = solver.build_payload(challenge, solution)

# 4. Submit
requests.post("https://example.com/api/action", json={
    "data": "your_data",
    "captcha": payload
})

Example 4: All Algorithms

from altcha_solver import AltchaSolver

solver = AltchaSolver()

# PBKDF2/SHA-256
solver.solve({"parameters": {"algorithm": "PBKDF2/SHA-256", ...}})

# PBKDF2/SHA-384
solver.solve({"parameters": {"algorithm": "PBKDF2/SHA-384", ...}})

# PBKDF2/SHA-512
solver.solve({"parameters": {"algorithm": "PBKDF2/SHA-512", ...}})

# Scrypt
solver.solve({"parameters": {"algorithm": "SCRYPT", ...}})

# Argon2id (requires argon2-cffi)
solver.solve({"parameters": {"algorithm": "ARGON2ID", ...}})

# SHA-256
solver.solve({"parameters": {"algorithm": "SHA-256", ...}})

# SHA-384
solver.solve({"parameters": {"algorithm": "SHA-384", ...}})

# SHA-512
solver.solve({"parameters": {"algorithm": "SHA-512", ...}})

Performance

Benchmark Results (prefix="00", single thread):

Algorithm Parameters Counter Found Solve Time Dependency
SHA-256 - 96 0.2 ms Native
SHA-384 - 217 0.4 ms Native
SHA-512 - 1119 1.8 ms Native
PBKDF2/SHA-256 cost=2000 455 585 ms Native
PBKDF2/SHA-384 cost=2000 182 355 ms Native
PBKDF2/SHA-512 cost=2000 543 1038 ms Native
Scrypt N=1024, r=8 12 50 ms Native
Argon2id t=2, m=1024 3 5 ms argon2-cffi

Iterations per Second (approximate):

Algorithm Cost Iter/sec
SHA-256 - ~500,000
SHA-384 - ~400,000
SHA-512 - ~350,000
PBKDF2/SHA-256 2000 ~780
PBKDF2/SHA-256 5000 ~330
Scrypt N=16384 ~15
Argon2id t=3, m=64MB ~3

Optimization Tips:

  1. Lower cost = faster: cost=2000 is 2.5x faster than cost=5000
  2. Short prefix = faster: Prefix "00" finds solution in ~256 iterations on average
  3. Parallel solving: Pre-compute challenges in parallel threads
  4. Batch requests: Fetch next challenge while solving current one

How It Works

Proof-of-Work Concept

Altcha uses computational puzzles instead of human verification:

  1. Server generates challenge with random parameters
  2. Client computes by iterating counter values
  3. Client finds solution when derived key matches criteria
  4. Server verifies the solution matches expected result

Password Construction

All algorithms use the same password format:

┌─────────────────────────────────────────────┐
│  Bytes 0-15:  nonce (from hex string)       │
│  Bytes 16-19: counter (4 bytes, big-endian) │
└─────────────────────────────────────────────┘

Example for counter = 494 (0x000001EE):
  nonce:    4d b2 e1 ee 61 08 47 6c ba 89 72 f3 9c f9 00 b9
  counter:  00 00 01 ee
  password: 4d b2 e1 ee 61 08 47 6c ba 89 72 f3 9c f9 00 b9 00 00 01 ee

Prefix Length and Solutions

Prefix Length Hex Chars Avg Iterations Uniqueness
1 byte 2 ("00") 256 Multiple solutions
2 bytes 4 65,536 Few solutions
4 bytes 8 4 billion+ Usually unique
8+ bytes 16+ Exactly 1 Always unique

Testing

Run the test suite:

# Verify all algorithms
python examples/verify_algorithm.py

# Performance benchmark
python examples/benchmark.py

# Basic usage
python examples/basic_usage.py

# Batch processing
python examples/batch_solver.py

Expected output:

============================================================
ALTCHA ALGORITHM VERIFICATION
============================================================

Test 1: PBKDF2 with short prefix
  Counter:     491
  Verified:    PASS

Test 2: PBKDF2 with exact counter verification
  Target:      1234
  Found:       1234
  Verified:    PASS

Test 3: Multiple valid solutions for short prefix
  Valid:       [491, 494, 903]
  Verified:    PASS

Test 4: Solution verification
  Valid check:   PASS
  Invalid check: PASS

============================================================
RESULTS: 4 passed, 0 failed
============================================================

Validation

This solver has been validated against:


Limitations

  • Not a bypass: PoW is designed to be solvable by any computer
  • Rate limiting: Servers may implement additional rate limits
  • Challenge expiration: Challenges typically expire after 2-5 minutes
  • Signature verification: Server validates challenge wasn't tampered

Security Considerations

What Altcha provides:

  • Bot deterrence through computational cost
  • Privacy (no tracking/fingerprinting)
  • Accessibility (no visual challenges)

What Altcha does NOT provide:

  • Human verification
  • Strong bot prevention (determined attackers can parallelize)

License

MIT License - See LICENSE for details.


Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Submit a pull request

References

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

altcha_solver-1.0.0.tar.gz (13.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

altcha_solver-1.0.0-py3-none-any.whl (12.8 kB view details)

Uploaded Python 3

File details

Details for the file altcha_solver-1.0.0.tar.gz.

File metadata

  • Download URL: altcha_solver-1.0.0.tar.gz
  • Upload date:
  • Size: 13.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for altcha_solver-1.0.0.tar.gz
Algorithm Hash digest
SHA256 e33180fbccf2ae18289fad71a7e74b3053136b2241e314774415c80e3dff0e19
MD5 b905d1b11d5aa656b33bb5f9d42a4f79
BLAKE2b-256 500a2431f1435b6252243405918de649b954f7c1c4cd79091d7e33af8ab7675f

See more details on using hashes here.

Provenance

The following attestation bundles were made for altcha_solver-1.0.0.tar.gz:

Publisher: publish.yml on opastorello/altcha-solver

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file altcha_solver-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: altcha_solver-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 12.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for altcha_solver-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 475378b5273b8b7f63e9dd1166561cff273391d90e89cede4c43732566a09c99
MD5 f02aad3a4b9bfa8f1608fe188dc62d5f
BLAKE2b-256 ffdceee635cb338f88c5673e5c38fd42d33b1e4139bcf5b545051d56a54f1ead

See more details on using hashes here.

Provenance

The following attestation bundles were made for altcha_solver-1.0.0-py3-none-any.whl:

Publisher: publish.yml on opastorello/altcha-solver

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page