requests और httpx के साथ Python में CaptchaFox कैसे हल करें

solve captchafox in python - How to Solve CaptchaFox in Python With requests and httpx

Python में CaptchaFox हल करने के लिए, capskip पैकेज से solver.captchafox() को sitekey और पेज URL के साथ कॉल करें, लौटे हुए token को cf-captcha-response फॉर्म फ़ील्ड में रखें, और वह रिक्वेस्ट उसी user agent के साथ भेजें जो token के साथ वापस आया था। Python कोड आमतौर पर इसी आख़िरी स्टेप पर गड़बड़ाता है। requests और httpx, दोनों डिफ़ॉल्ट रूप से User-Agent header में अपनी ही पहचान बताते हैं, और जो साइट token को उसी ब्राउज़र से आने की उम्मीद करती है जिसने उसे बनाया था, वह ऐसी रिक्वेस्ट ठुकरा देती है, इसलिए पूरी तरह कामयाब रहा solve भी सबमिट पर फेल हो सकता है। CapSkip ने CaptchaFox को वर्ज़न 1.4.0 में जोड़ा। यह गाइड key, कॉल, सबमिट, दोबारा कोशिशें और एक साथ कई solve चलाना कवर करती है।

आपको क्या चाहिए

  • किसी Windows मशीन पर चल रहा CapSkip 1.4.0 या उसके बाद का संस्करण। CaptchaFox उसी रिलीज़ में जोड़ा गया था, Friendly Captcha और Capy Puzzle के साथ।
  • Python 3.10 या उसके बाद का संस्करण, और capskip पैकेज का 1.3.0 या उसके बाद का वर्ज़न, जो captchafox() method वाली पहली रिलीज़ है। सैंपल requests भी इस्तेमाल करते हैं, और parallel solve वाला सेक्शन httpx इस्तेमाल करता है।
  • टारगेट पेज से दो वैल्यू: sitekey, और उस पेज का URL जिस पर widget चलता है। स्टेप 1 दिखाता है कि key कहाँ होती है, और वहाँ रहते हुए किस script टैग को देखना है।
  • सॉल्वर के लिए एक पता। Local मोड में CapSkip केवल उसी डिवाइस के लिए 127.0.0.1 पर जवाब देता है; Server मोड में वह आपके नेटवर्क पते या पब्लिक IP पर सुनता है, ताकि किसी दूसरी मशीन पर चल रही script API के ज़रिए उसे कॉल कर सके। दोनों यहाँ सेट किए जाते हैं: कनेक्शन सेटिंग्स.
# Quoted, so cmd.exe does not read >= as a redirect
pip install "capskip>=1.3.0" requests httpx

स्टेप 1: sitekey और widget का source पढ़ें

sitekey सार्वजनिक होती है, हर विज़िटर के लिए एक जैसी होती है, और आमतौर पर sk_ से शुरू होती है। ज़्यादातर पेज उसे widget के container पर रखते हैं: captchafox class वाला एक div, जिस पर data-sitekey attribute होता है। जो पेज widget को अपनी script से बनाता है, वह key इसके बजाय एक captchafox.render कॉल को पास करता है, और जब इनमें से कुछ भी आपके लाए गए HTML में न दिखे, तो key Network टैब में होती है: api.captchafox.com को गई रिक्वेस्ट में /captcha/ के बाद वाला path segment ही key है।

पेज पढ़ते समय यह भी जाँचें कि कौन सी script widget लोड करती है। ज़्यादातर साइटें उसे cdn.captchafox.com से लोड करती हैं और उन्हें एक सादा token मिलता है। कुछ प्लेटफ़ॉर्म इसके बजाय s.uicdn.com/mampkg/ से एक पैकेज एम्बेड करते हैं, और वे साइटें MAM_ से शुरू होने वाले token की उम्मीद करती हैं। गलत वाले के लिए हल करने पर भी token मिलता है, बस ऐसे फ़ॉर्मेट में जिसे साइट फिर मना कर देती है, इसलिए यह जाँच आपकी एक उलझन भरी दोपहर बचा लेती है। MAM पेजों पर key खुद script के src में, ?key= के बाद, हो सकती है, और वही CDN दूसरे, असंबंधित पैकेज भी सर्व करता है, इसलिए host के बजाय captchafox पैकेज path से मिलान करें।

import re

import requests

PAGE_URL = "https://example.com/signup"
session = requests.Session()
html = session.get(PAGE_URL, timeout=30).text

# The container: <div class="captchafox" data-sitekey="sk_...">
tag = re.search(r'<[^>]*class="(?:[^"]*\s)?captchafox(?:\s[^"]*)?"[^>]*>', html)
key = tag and re.search(r'data-sitekey="([^"]+)"', tag.group(0))
# MAM pages may carry the key in the script src instead.
key = key or re.search(r'captchafox[^"]*/api\.js\?key=([^"&]+)', html)
sitekey = key.group(1) if key else None

# The MAM build expects a MAM_ token; everything else is the default.
uses_mam = "mampkg/@mamdev/core.frontend.libs.captchafox" in html
print(sitekey, uses_mam)

class वाला pattern whitespace से घिरा है, ताकि captchafox-container जैसी class वाला कोई wrapper element गलती से मैच न हो जाए। यह attribute वैल्यू के चारों ओर double quotes की उम्मीद करता है, जैसे CaptchaFox का अपना snippet उन्हें लिखता है।

स्टेप 2: captchafox() कॉल

Python में CaptchaFox हल करने के लिए आपको एक ही method चाहिए, जो sitekey और पेज URL लेता है, साथ में वैकल्पिक keyword arguments भी। standard widget के लिए उसे बस इन्हीं दो की ज़रूरत होती है।

# pip install "capskip>=1.3.0"
from capskip import CapSkip

solver = CapSkip(host="127.0.0.1", port=8080)

result = solver.captchafox("YOUR_SITEKEY", "https://example.com/signup")

print(result["token"])           # goes in cf-captcha-response
print(result.get("userAgent"))   # send this as the User-Agent

नतीजा एक सादा dict है। token और code में एक ही स्ट्रिंग होती है, और token का नाम उसी फ़ील्ड पर रखा गया है जिसे वह भरता है। userAgent उस ब्राउज़र की पहचान है जिसने token बनाया, यानी CapSkip का अपना ब्राउज़र, न कि कोई चीज़ जो आपने भेजी हो। यह key तभी मौजूद होती है जब solve ने कोई user agent रिपोर्ट किया हो, इसलिए इसे square brackets से नहीं, result.get() से पढ़ें, वरना बिना user agent वाला कोई इक्का-दुक्का solve उसी लाइन पर KeyError उठा देगा जिसे फॉर्म सबमिट करना था।

पेज URL वही पेज होना चाहिए जिस पर widget असल में चलता है। CaptchaFox हर key को अनुमत डोमेन की एक सूची के साथ रजिस्टर करता है और कुछ भी जारी करने से पहले host जाँचता है, इसलिए गलत पेज के साथ भेजी गई key हर बार मना कर दी जाती है, कभी-कभार नहीं। कोई redirect, छोटा किया गया लिंक या सर्च रिज़ल्ट काम नहीं करेगा।

method जिन ऑप्शन को स्वीकार करता है

जो पेज MAM पैकेज लोड करता है, उसके लिए उसके script टैग से पैकेज path लेकर api_server के रूप में पास करें। रिक्वेस्ट जाने से पहले SDK हर वह keyword argument हटा देता है जिसकी वैल्यू None हो, इसलिए आप यह ऑप्शन हर कॉल पर पास कर सकते हैं और फ़ैसला स्टेप 1 की जाँच पर छोड़ सकते हैं।

# Copied from the script tag on MAM pages.
MAM_PACKAGE = "https://s.uicdn.com/mampkg/@mamdev/core.frontend.libs.captchafox/"

result = solver.captchafox(
    sitekey,
    PAGE_URL,
    # None is dropped, so the standard widget sends nothing extra.
    api_server=MAM_PACKAGE if uses_mam else None,
)

api_server के अलावा captchafox() proxy, proxytype और useragent लेता है, साथ में सेकंड में हर कॉल का अपना timeout और polling_interval भी। useragent ऑप्शन दूसरी सर्विसों के साथ compatibility के लिए स्वीकार किया जाता है और जानबूझकर लागू नहीं किया जाता, क्योंकि CapSkip एक असली ब्राउज़र में हल करता है, जिसकी अपनी एक सुसंगत पहचान होती है। कोई और keyword, खाली sitekey या URL, type और uri के बिना proxy dict, या HTTP, HTTPS, SOCKS5 या SOCKS5H के अलावा कोई proxy type, रिक्वेस्ट भेजे जाने से पहले ही ValidationException उठाता है।

स्टेप 3: उसी user agent के साथ सबमिट करें जिसने token बनाया

Python में CaptchaFox हल करते समय यही वह स्टेप है जो तय करता है कि साइट token स्वीकार करेगी या नहीं। डिफ़ॉल्ट रूप से requests, User-Agent में python-requests और उसके बाद अपना वर्ज़न नंबर भेजता है, और httpx, python-httpx और उसके बाद अपना वर्ज़न नंबर। इनमें से कोई भी वह ब्राउज़र नहीं है जिसने token बनाया। लौटी हुई वैल्यू को उस रिक्वेस्ट पर कॉपी करें जो token ले जाती है।

# session is the one Step 1 fetched the page with, so it carries its cookies.
ua = result.get("userAgent")
resp = session.post(
    PAGE_URL,  # or wherever the form's action attribute points
    data={"email": "YOUR_EMAIL", "cf-captcha-response": result["token"]},
    # Per request, not on session.headers: the next token may differ.
    headers={"User-Agent": ua} if ua else {},
    timeout=30,
)
print(resp.status_code)

post() को पास किया गया header सिर्फ़ उसी एक रिक्वेस्ट के लिए session के डिफ़ॉल्ट पर merge होता है, इसलिए session अपनी cookies रखता है और बाद की हर रिक्वेस्ट पहले की तरह ही जाती है। इसके बजाय session.headers सेट करने से एक solve का user agent उसके बाद की हर रिक्वेस्ट पर लग जाएगा, अगले token के सबमिट पर भी। httpx में, पेज को एक ही httpx.Client से लाएँ और उसी से सबमिट करें, ताकि cookies साथ बनी रहें, और data, headers और timeout को उसी तरह उसके post() को पास करें।

दो और नियम इस बात से निकलते हैं कि CaptchaFox साइट की तरफ़ token की जाँच कैसे करता है। हर token एक ही बार, और सिर्फ़ थोड़े समय के भीतर verify किया जा सकता है, इसलिए तभी हल करें जब आप सबमिट करने के लिए तैयार हों, और तुरंत सबमिट करें। और token को opaque मानें: उसे न काटें, न दोबारा encode करें, न उसका फ़ॉर्मेट बदलें। कुछ साइटें उसे फॉर्म पोस्ट के बजाय JSON बॉडी में भेजती हैं, इसलिए DevTools खोलकर फॉर्म को एक बार हाथ से सबमिट करें और पेज जो भेजता है ठीक वैसा ही करें।

स्टेप 4: दोबारा कोशिश, challenge के प्रकार और timeout

CaptchaFox कौन सा challenge दिखाएगा, यह आप नहीं चुनते। ज़्यादातर solve में कुछ भी नहीं दिखता, क्योंकि ब्राउज़र से मिले संकेत अपने आप ही जाँच पास कर लेते हैं, और जब slide puzzle आता है, तो CapSkip आमतौर पर उसे पूरा कर देता है। Image-select और ऑडियो challenge दुर्लभ हैं और हल नहीं किए जाते: वे timeout के आख़िर में नहीं, बल्कि कुछ ही सेकंड में एक ApiException के रूप में लौटते हैं, जिसके मैसेज में ERROR_CAPTCHA_UNSOLVABLE होता है। नई कोशिश में आमतौर पर कुछ और आता है, इसलिए दोबारा कोशिश करने के आपके पास दो तरीके हैं।

  • CapSkip में। सेटिंग्स के CaptchaFox सेक्शन में Retries (0-3) होता है, जो डिफ़ॉल्ट रूप से 0 पर रहता है। इसे बढ़ाने पर CapSkip बिना सपोर्ट वाले challenges, समय खत्म हो चुकी कोशिशों और ब्राउज़र errors पर अपने आप फिर से कोशिश करता है, और साइट जिस key को मना कर दे, उसे कभी दोबारा नहीं आज़माता। हर अतिरिक्त कोशिश एक कॉल में ज़्यादा से ज़्यादा एक Row Timeout जोड़ सकती है, जो डिफ़ॉल्ट रूप से 150 सेकंड है, इसलिए इसे बढ़ाएँ तो captchafox() को लंबा timeout पास करें।
  • आपके कोड में। exception को catch करें और फिर से कॉल करें, जैसा नीचे है। बस एक पेच है: मना की गई key भी API के ज़रिए unsolvable के रूप में ही दिखती है, इसलिए गलत डोमेन पर इस्तेमाल हुई key को भी दोबारा आज़माया जाता है। वह हर कोशिश में कुछ ही सेकंड में फेल होती है और एक बार भी कामयाब नहीं होती, और यही उसकी पहचान है।
from capskip.exceptions import ApiException


def solve_captchafox(sitekey, url, attempts=3, **options):
    for attempt in range(1, attempts + 1):
        try:
            return solver.captchafox(sitekey, url, **options)
        except ApiException as exc:
            # Select, audio and unreadable slide draws come back
            # unsolvable; redraw. Anything else, such as a wrong
            # API key, is final.
            if "UNSOLVABLE" not in str(exc) or attempt == attempts:
                raise

captchafox() क्लाइंट के recaptchaTimeout पर पोलिंग करता है, जो डिफ़ॉल्ट रूप से 300 सेकंड है, क्योंकि यह एक असली ब्राउज़र session है। CapSkip की अपनी समय सीमाएँ भी होती हैं। कोई टास्क 10 CaptchaFox threads (Max. Threads) में से किसी एक के लिए 250 सेकंड (Wait Timeout) तक इंतज़ार कर सकता है, और एक कोशिश को 150 सेकंड (Row Timeout) मिलते हैं। जब Retries 0 पर हो और कोई thread खाली हो, तो फेल हुई कोशिश SDK के 300 सेकंड पूरे होने से काफ़ी पहले ही CapSkip से ApiException के रूप में आप तक पहुँच जाती है; अगर टास्क देर तक queue में इंतज़ार करता है, तो SDK पहले अपनी सीमा तक पहुँच सकता है और इसके बजाय TimeoutException उठा सकता है।

एक साथ कई tokens हल करना

Python में AsyncCapSkip एक असली asyncio क्लाइंट है, कोई उपनाम नहीं, इसलिए asyncio.gather कई solve साथ-साथ चलाता है। इसे httpx के async क्लाइंट के साथ इस्तेमाल करें, और हर token को सबमिट होने तक उसके अपने user agent के साथ रखें।

import asyncio

import httpx
from capskip import AsyncCapSkip

solver = AsyncCapSkip(host="127.0.0.1", port=8080)


async def solve_and_submit(client, sitekey, url, form):
    await client.get(url)  # the form's cookies land in client
    result = await solver.captchafox(sitekey, url)
    ua = result.get("userAgent")
    return await client.post(
        url,
        data={**form, "cf-captcha-response": result["token"]},
        headers={"User-Agent": ua} if ua else {},
    )


async def main(jobs):
    async with httpx.AsyncClient(timeout=30) as client:
        return await asyncio.gather(
            *(solve_and_submit(client, *job) for job in jobs),
            return_exceptions=True,
        )

दो सीमाएँ लागू होती हैं। CapSkip डिफ़ॉल्ट रूप से एक साथ 10 CaptchaFox solve चलाता है, और बाकी किसी खाली thread के लिए 250 सेकंड वाले Wait Timeout तक इंतज़ार करते हैं, इसलिए सामान्य solve समय पर पचास jobs पर एक gather ठीक रहता है; इससे बड़े batch के लिए Max. Threads बढ़ाएँ या छोटे समूहों में gather करें। और CaptchaFox ब्राउज़र के साथ-साथ नेटवर्क को भी स्कोर करता है, इसलिए एक ही पते से बहुत सारे solve challenge की दर बढ़ा देते हैं। CapSkip के CaptchaFox सेक्शन में प्रॉक्सी कॉन्फ़िगर करें, या हर कॉल पर type और uri वाला एक proxy dict पास करें, और सबमिट भी उसी exit से भेजें। asyncio पैटर्न पर ज़्यादा जानकारी यहाँ है: Python में समानांतर रूप से कैप्चा हल करने की गाइड.

सॉल्वर को किसी दूसरी मशीन पर चलाना

जब तक script और CapSkip एक ही Windows PC पर हों, 127.0.0.1 सही है। जैसे ही Python कोड किसी VPS, कंटेनर, CI runner या होस्टेड notebook पर जाता है, loopback गलत मशीन की ओर इशारा करता है और पहला ही solve एक NetworkException उठाता है। CapSkip को Server मोड पर कर दें और वह आपके नेटवर्क पते या पब्लिक IP पर सुनने लगता है, ताकि इनमें से कोई भी उसी API के ज़रिए उसे कॉल कर सके। जब रास्ता इंटरनेट से होकर जाए तो स्टैटिक पब्लिक IP इस्तेमाल करें, API key validation चालू करें, और Windows Firewall नियम से पोर्ट को सिर्फ़ अपेक्षित पतों तक सीमित रखें। सॉल्वर अब भी आपकी अपनी Windows मशीन है, और solve अब भी बिना मीटर वाले हैं।

SDK एनवायरनमेंट वेरिएबल खुद नहीं पढ़ता। CAPSKIP_HOST, CAPSKIP_PORT और CAPSKIP_API_KEY को अपने कोड में पढ़ें और उन्हें constructor को पास करें, जैसा पूरा उदाहरण करता है, ताकि वही script आपकी डेस्क पर भी चले और सर्वर पर भी।

पूरा चलने वाला उदाहरण

# pip install "capskip>=1.3.0" requests
import os
import re

import requests
from capskip import CapSkip
from capskip.exceptions import (ApiException, CapSkipError,
                                TimeoutException, ValidationException)

PAGE_URL = "https://example.com/signup"
# Copied from the script tag on MAM pages.
MAM_PACKAGE = "https://s.uicdn.com/mampkg/@mamdev/core.frontend.libs.captchafox/"

solver = CapSkip(
    apiKey=os.getenv("CAPSKIP_API_KEY", "capskip"),
    host=os.getenv("CAPSKIP_HOST", "127.0.0.1"),
    port=int(os.getenv("CAPSKIP_PORT", "8080")),
)
session = requests.Session()

html = session.get(PAGE_URL, timeout=30).text
tag = re.search(r'<[^>]*class="(?:[^"]*\s)?captchafox(?:\s[^"]*)?"[^>]*>', html)
key = tag and re.search(r'data-sitekey="([^"]+)"', tag.group(0))
key = key or re.search(r'captchafox[^"]*/api\.js\?key=([^"&]+)', html)
if not key:
    raise SystemExit("No sitekey in the HTML; find it in DevTools.")
api_server = MAM_PACKAGE if "mampkg/@mamdev/core.frontend.libs.captchafox" in html else None

try:
    for attempt in range(1, 4):
        try:
            result = solver.captchafox(key.group(1), PAGE_URL,
                                       api_server=api_server)
            break
        except ApiException as exc:
            # Select, audio and unreadable slide draws come back unsolvable.
            if "UNSOLVABLE" not in str(exc) or attempt == 3:
                raise
            print(f"attempt {attempt}: {exc}")
except ValidationException as exc:
    raise SystemExit(f"not sent: {exc}")
except TimeoutException:
    raise SystemExit("gave up waiting; recaptchaTimeout is 300 seconds")
except CapSkipError as exc:
    # A third unsolvable draw, a refused key, or CapSkip unreachable.
    raise SystemExit(f"solve failed: {exc!r}")

ua = result.get("userAgent")
resp = session.post(
    PAGE_URL,  # or wherever the form's action attribute points
    data={"email": "YOUR_EMAIL", "cf-captcha-response": result["token"]},
    headers={"User-Agent": ua} if ua else {},
    timeout=30,
)
print(resp.status_code, "UA sent:", bool(ua))

अगर हर रन पर solve तुरंत फेल हो जाए, तो सबसे पहले पेज URL जाँचें, क्योंकि अपने रजिस्टर्ड डोमेन के बाहर इस्तेमाल हुई key हर बार एक ही तरह फेल होती है। जब regex को कुछ नहीं मिलता, तो पेज widget को script से बनाता है, और key render कॉल में या Network टैब में होती है, जैसा स्टेप 1 में बताया गया है। इस method के पीछे का raw endpoint यहाँ दर्ज है: CaptchaFox API रेफ़रेंस.

आम errors और उनका मतलब

आप जो देखते हैंकारणफिक्स
साइट उस token को ठुकरा देती है जिसे CapSkip ने हल हुआ बताकर लौटाया थासबमिट python-requests या python-httpx के रूप में गया, उस ब्राउज़र के रूप में नहीं जिसने token बनाया थाउस रिक्वेस्ट पर result.get("userAgent") को User-Agent header के रूप में भेजें
user agent मेल खाने के बावजूद ठुकराया गयापेज MAM पैकेज लोड करता है और solve में डिफ़ॉल्ट widget इस्तेमाल हुआ, या इसका उल्टाscript टैग पढ़ें और api_server को उसके मुताबिक़ सेट करें
userAgent पर KeyErrorsolve ने कोई user agent रिपोर्ट नहीं किया, और यह key तभी मौजूद होती है जब वह रिपोर्ट करेइसे result.get() से पढ़ें और header तभी भेजें जब कोई वैल्यू हो
एक ही key के लिए हर बार तुरंत एक ApiExceptionपेज URL उन डोमेन से बाहर है जिनके लिए key रजिस्टर है, या key ही गलत हैवही पेज भेजें जिस पर widget चलता है, कोई redirect या सर्च रिज़ल्ट नहीं, और key दोबारा जाँचें
कभी-कभार आने वाला ApiException, जिसमें ERROR_CAPTCHA_UNSOLVABLE होता हैCaptchaFox ने image-select या ऑडियो challenge दिखाया, या slide का कोई ऐसा रूप जिसे CapSkip पढ़ नहीं सकाकोड में दोबारा कोशिश करें, या CapSkip की CaptchaFox सेटिंग्स में Retries बढ़ाएँ
एक बार चल चुका token दूसरी बार फेल हो जाता हैहर token एक ही बार verify होता है और जल्दी expire हो जाता हैहर सबमिट के लिए नया token हल करें, और तुरंत सबमिट करें
रन आगे बढ़ने के साथ ज़्यादा challenges, फिर इनकारहर solve एक ही पते से आता है, और CaptchaFox नेटवर्क को स्कोर करता हैsolve को एक प्रॉक्सी पूल में बाँटें, और सबमिट भी उसी exit से करें
कुछ भी भेजे जाने से पहले ही ValidationExceptionखाली sitekey या URL, कोई ऐसा keyword argument जो यह method नहीं लेता, या कोई ऐसा proxy type जिसे CapSkip स्वीकार नहीं करताजाँचें कि sitekey मिली थी, और संदेश में बताए गए argument को ठीक करें या हटा दें
पहली कॉल पर NetworkExceptionCapSkip चल नहीं रहा, या host और port गलत हैंCapSkip शुरू करें, फिर देखें कि उसे Local मोड में होना चाहिए या Server मोड में

FAQ

क्या result["code"], result["token"] से अलग है?

नहीं, CaptchaFox के लिए दोनों एक ही स्ट्रिंग हैं। code वह फ़ील्ड है जिसे CapSkip का हर method भरता है, जिससे पुराना कोड बिना बदलाव के चलता रहता है, और token वह नाम है जो फॉर्म की उम्मीद से मेल खाता है। नए कोड में token इस्तेमाल करें, ताकि वह उसी फ़ील्ड जैसा पढ़ा जाए जिसे वह भरता है।

क्या मैं token को Playwright या Selenium session में इस्तेमाल कर सकता हूँ?

हाँ, बशर्ते सबमिट उसी user agent के साथ जाए जो CapSkip ने लौटाया। Playwright context बनते समय ही user agent तय कर देता है, इसलिए पहले हल करें, फिर browser.new_context(user_agent=ua) से context खोलें, फॉर्म लोड करें, token को cf-captcha-response फ़ील्ड में लिखें और सबमिट करें। Chrome के साथ Selenium में, driver शुरू होने से पहले Chrome options में उस वैल्यू के साथ user-agent switch जोड़ें, या चल रहे session को driver.execute_cdp_cmd("Network.setUserAgentOverride", {"userAgent": ua}) से बदलें। अगर आपके ऑटोमेशन को किसी और काम के लिए ब्राउज़र की ज़रूरत नहीं है, तो ऊपर वाला requests तरीका ज़्यादा आसान है।

क्या किसी होस्टेड प्लेटफ़ॉर्म पर चल रही Python script सॉल्वर तक पहुँच सकती है?

हाँ। कनेक्शन सेटिंग्स में CapSkip को Server मोड पर कर दें ताकि वह loopback के बजाय किसी नेटवर्क पते पर सुने, वह पता अपनी script में CAPSKIP_HOST से पढ़ें, और उसे CapSkip() को पास करें। VPS, कंटेनर होस्ट, CI runner और होस्टेड notebook, सब उसी HTTP API के ज़रिए जुड़ते हैं। जब रास्ता इंटरनेट से होकर जाए तो स्टैटिक पब्लिक IP और फ़ायरवॉल नियम इस्तेमाल करें। सॉल्वर आपके अपने हार्डवेयर पर ही रहता है, इसलिए solve की गिनती के तरीके में कुछ नहीं बदलता।

यह C# वर्ज़न से कैसे अलग है?

कॉल और नियम वही हैं; फँसने की जगहें अलग हैं। C# में, जब तक आप खुद न जोड़ें, HttpClient कोई User-Agent भेजता ही नहीं। Python में दोनों आम क्लाइंट इसके बजाय अपना ही नाम भेजते हैं, python-requests या python-httpx, जिसे साइट उतनी ही आसानी से मना कर सकती है। .NET वाला पहलू यहाँ कवर किया गया है: C# CaptchaFox गाइड.

संक्षेप में

Python में CaptchaFox हल करने के लिए, sitekey को captchafox container, render कॉल या Network टैब से पढ़ें, और ध्यान दें कि पेज MAM पैकेज लोड करता है या नहीं। solver.captchafox() को sitekey और असली पेज URL के साथ कॉल करें, और api_server सिर्फ़ MAM पेजों के लिए जोड़ें। result["token"] को cf-captcha-response में पोस्ट करें, User-Agent header के रूप में result.get("userAgent") के साथ, एक बार और तुरंत। unsolvable challenge आने पर दोबारा कोशिश करें, volume बढ़ने के साथ प्रॉक्सी जोड़ें, और जैसे ही script सॉल्वर की मशीन से बाहर जाए, Server मोड पर चले जाएँ।

image-select draw पर दोबारा कोशिश करना ही वह एक आदत है जिसकी इस टाइप को ज़रूरत है, और अपनी ही मशीन पर चलने वाले लोकल captcha सॉल्वर के साथ हर दोबारा कोशिश में बस कुछ सेकंड लगते हैं, किसी और बिल किए गए solve का ख़र्च नहीं।