captchaforge 0.2.7

Automatic CAPTCHA detection and multi-strategy solving for chromiumoxide-driven headless browsers (Cloudflare Turnstile, reCAPTCHA v2/v3, hCaptcha, image grids, audio, sliders).
Documentation
# Community-contributed captcha provider rules.
#
# Each [[provider]] entry adds a TOML-driven detector to the registry.
# See `captchaforge::detect::rules` for the full schema. Detection is
# OR across triggers; first match wins.
#
# Priority guidance — interleave with built-ins:
#     5    challenge_page (CF interstitial — built-in)
#    10    turnstile (built-in)
#    11–19 reserved for vendor-specific overrides
#    20    recaptcha (built-in)
#    30    hcaptcha (built-in)
#    40    image_captcha (built-in)
#    50    audio_captcha (built-in)
#    60    pow_captcha (built-in)
#    65    canvas_captcha (built-in)
#    75    slider_captcha (built-in)
#    85    multi_step (built-in)
#    90    shadow_dom (built-in)
#    100+  catch-alls / community vendors
#
# When you ship a new provider, give it a priority that runs BEFORE the
# generic detector that would otherwise catch it (e.g. Geetest v4 must
# precede the generic slider_captcha at 75).

[[provider]]
name = "datadome"
priority = 11

[provider.triggers]
selectors = ["[data-datadome]", ".datadome-captcha", "iframe[src*='captcha-delivery.com']"]
window_globals = ["DataDomeOptions", "ddjskey"]
script_src_contains = ["js.datadome.co", "captcha-delivery.com"]


[[provider]]
name = "akamai_bot_manager"
priority = 12

[provider.triggers]
selectors = ["[data-akamai-bot]", "iframe[src*='akamaihd.net/captcha']"]
window_globals = ["bmak", "_abck"]
script_src_contains = ["akamaihd.net/captcha", "akam.net/captcha", "akamaiedge.net"]


[[provider]]
name = "perimeterx_human"
priority = 13

# PerimeterX rebranded to HUMAN Security; both old and new signatures
# are kept here so the rule covers fleet that hasn't migrated.
[provider.triggers]
selectors = ["#px-captcha", ".px-captcha-error-container", "[data-px-captcha]"]
window_globals = ["_pxAppId", "PX", "_humanSecurity"]
script_src_contains = ["client.px-cdn.net", "captcha.px-cdn.net", "human-security.com/captcha"]


[[provider]]
name = "arkose_funcaptcha"
priority = 14

# Arkose Labs (formerly FunCaptcha) — gamified rotation/orientation
# challenges. Detection signatures cover both branding eras.
[provider.triggers]
selectors = ["[data-pkey]", "#funcaptcha", ".arkose-iframe", "iframe[src*='arkoselabs.com']"]
window_globals = ["ArkoseEnforcement", "FunCaptcha"]
script_src_contains = ["client-api.arkoselabs.com", "funcaptcha.com"]


[[provider]]
name = "geetest_v4"
priority = 15

# Geetest v4 — slider/click puzzle. Must run BEFORE the generic
# slider_captcha (priority 75), otherwise the generic detector wins.
[provider.triggers]
selectors = [".geetest_box", ".geetest_panel", "[data-gt]"]
window_globals = ["initGeetest4", "Geetest"]
script_src_contains = ["static.geetest.com/v4", "static.geetest.com/static/js/gt4"]


[[provider]]
name = "geetest_v3"
priority = 16

# Geetest v3 (legacy slider). Distinct selectors from v4 so they
# don't false-match each other.
[provider.triggers]
selectors = [".geetest_holder", ".geetest_radar_btn", ".geetest_slider_button"]
window_globals = ["initGeetest"]
script_src_contains = ["static.geetest.com/static/tools/api.js", "geetest.com/v3"]


[[provider]]
name = "aws_waf_captcha"
priority = 17

# AWS WAF Captcha — visible visual challenge issued by AWS WAF
# protections. Distinct from the AWS Bot Control silent challenge,
# which has no captcha widget to solve.
[provider.triggers]
selectors = ["#captcha-container", "[data-aws-waf-captcha]", "iframe[src*='captcha.awswaf.com']"]
window_globals = ["AwsWafIntegration", "AwsWafCaptcha"]
script_src_contains = ["captcha.awswaf.com", "captcha-prod.awswaf.com"]


[[provider]]
name = "friendly_captcha"
priority = 18

# Friendly Captcha — privacy-preserving PoW. Distinct from generic
# pow_captcha (priority 60) so per-vendor routing is possible.
[provider.triggers]
selectors = [".frc-captcha", "[data-sitekey][data-puzzle-endpoint]"]
script_src_contains = ["cdn.jsdelivr.net/npm/friendly-challenge", "friendlycaptcha.com"]


[[provider]]
name = "mtcaptcha"
priority = 19

# MTCaptcha — accessibility-focused visual + audio captcha.
[provider.triggers]
selectors = [".mtcaptcha-container", "#mtcaptcha", ".mtcaptcha-widget"]
window_globals = ["mtcaptcha", "mtcaptchaConfig"]
script_src_contains = ["service.mtcaptcha.com", "service2.mtcaptcha.com"]


[[provider]]
name = "wp_math_captcha"
priority = 100

# Generic WordPress math captcha — common on contact forms.
# Runs LATE so per-vendor detectors win when both match.
[provider.triggers]
selectors = [
    "input[name='captcha-result']",
    "input[name='math_captcha']",
    "input[id*='math_captcha']",
    ".math-captcha-question",
    ".cptch_input",   # Captcha by BestWebSoft plugin
]