सही User Agent के साथ Node.js में CaptchaFox कैसे हल करें

Node.js में CaptchaFox हल करने के लिए, capskip पैकेज के captchafox method को sitekey और पेज URL के साथ कॉल करें, फिर लौटे हुए token को cf-captcha-response फ़ील्ड में पोस्ट करें। उस पोस्ट के साथ तीन चीज़ें भेजें जो fetch आपके लिए खुद नहीं जोड़ता: पेज की सेट की हुई cookies, एक Referer, और वह user agent जो CapSkip ने token के साथ लौटाया। ज़्यादातर Node कोड user agent वाले इसी जाल में फँसता है। Node का built-in fetch हर सर्वर को बताता है कि उसका user agent node है, और जो साइट token को उसी ब्राउज़र से आने की उम्मीद करती है जिसने उसे बनाया था, वह ऐसी पोस्ट ठुकरा देती है, solve चाहे कितना भी अच्छा रहा हो। CapSkip ने CaptchaFox को वर्ज़न 1.4.0 में जोड़ा। यह गाइड key पढ़ना, कॉल, सबमिट, दोबारा कोशिशें और एक साथ कई साइन-अप चलाना कवर करती है।
आपको क्या चाहिए
- किसी Windows मशीन पर चल रहा CapSkip 1.4.0 या उसके बाद का संस्करण। CaptchaFox उसी रिलीज़ में जोड़ा गया था, Friendly Captcha और Capy Puzzle के साथ।
- Node.js 20.18.1 या उसके बाद का संस्करण, जो cheerio की सपोर्ट की हुई सबसे पुरानी रिलीज़ है। नए प्रोजेक्ट पर 22 या 24 इस्तेमाल करें, क्योंकि Node 20 अप्रैल 2026 में end of life पर पहुँच चुका है।
- capskip पैकेज का 1.3.0 या उसके बाद का वर्ज़न, जो captchafox method वाली पहली रिलीज़ है, और साथ में HTML पढ़ने के लिए cheerio।
- उस पेज का URL जो widget दिखाता है। sitekey, फॉर्म फ़ील्ड और widget का build, सब उसी पेज से मिलते हैं।
- सॉल्वर के लिए एक पता। Local मोड में CapSkip केवल उसी डिवाइस के लिए 127.0.0.1 पर जवाब देता है; Server मोड में वह आपके नेटवर्क पते या पब्लिक IP पर सुनता है, ताकि किसी दूसरी मशीन पर चल रही script API के ज़रिए उसे कॉल कर सके। दोनों यहाँ सेट किए जाते हैं: कनेक्शन सेटिंग्स.
# capskip 1.3.0 added captchafox(); cheerio reads the HTML npm install capskip cheerio
सैंपल top-level await वाले ES modules हैं। उन्हें .mjs extension के साथ सेव करें, या अपने package.json में type फ़ील्ड को module पर सेट करें, क्योंकि npm init अब वहाँ commonjs लिखता है। अगर आपका प्रोजेक्ट CommonJS है, तो capskip पैकेज require से भी लोड हो जाता है।
स्टेप 1: पेज fetch करें, उसकी cookies रखें और sitekey पढ़ें
Node का fetch कॉल के बीच कोई cookie नहीं रखता, इसलिए पेज जो session cookie सेट करता है, वह फॉर्म पोस्ट करने तक गायब हो चुकी होती है। जो साइट अपने CSRF token को उसी session से जोड़ती है, वह फिर पोस्ट ठुकरा देती है। cookies को Headers.getSetCookie() की मदद से खुद आगे ले जाएँ, जो हर Set-Cookie लाइन अलग-अलग लौटाता है। Node.js में Friendly Captcha हल करने की गाइड इस छोटे cookie jar को और विस्तार से समझाती है।
// npm install capskip cheerio
import * as cheerio from "cheerio";
const PAGE_URL = "https://example.com/signup";
// fetch() keeps no cookies between calls, so carry the page's own.
const jar = new Map();
const page = await fetch(PAGE_URL);
for (const line of page.headers.getSetCookie()) {
const pair = line.split(";")[0];
const eq = pair.indexOf("=");
jar.set(pair.slice(0, eq).trim(), pair.slice(eq + 1).trim());
}
const html = await page.text();
const $ = cheerio.load(html);sitekey सार्वजनिक होती है, हर विज़िटर के लिए एक जैसी होती है, और आमतौर पर sk_ से शुरू होती है। ज़्यादातर पेज उसे widget के container पर रखते हैं: captchafox class वाला एक div, जिस पर data-sitekey attribute होता है। जो पेज widget को अपनी script से बनाता है, वह key इसके बजाय एक captchafox.render कॉल को पास करता है। जब इनमें से कुछ भी आपके fetch किए गए HTML में न हो, तो DevTools खोलें: api.captchafox.com को, या MAM पेजों पर mam-api.captchafox.com को गई रिक्वेस्ट में /captcha/ के बाद वाला path segment ही key है।
वहाँ रहते हुए यह भी जाँचें कि पेज widget का कौन सा build लोड करता है। ज़्यादातर साइटें उसे cdn.captchafox.com से लोड करती हैं और एक सादे token की उम्मीद करती हैं। कुछ प्लेटफ़ॉर्म इसके बजाय s.uicdn.com/mampkg/ से एक पैकेज एम्बेड करते हैं, और वे साइटें MAM_ से शुरू होने वाले token की उम्मीद करती हैं। MAM पेज पर key खुद उस script के पते में, ?key= के बाद, हो सकती है। वही CDN दूसरे, असंबंधित पैकेज भी सर्व करता है, इसलिए host के बजाय captchafox पैकेज path से मिलान करें।
// The container, matched on the whole class name.
const widget = $(".captchafox").first();
// MAM pages may carry the key in the package's script src instead.
const mamSrc = $('script[src*="mampkg/@mamdev/core.frontend.libs.captchafox"]').attr("src");
const sitekey = widget.attr("data-sitekey")
?? (mamSrc && new URL(mamSrc, PAGE_URL).searchParams.get("key"))
?? html.match(/captchafox\.render\([\s\S]{0,300}?sitekey\s*:\s*["']([^"']+)/)?.[1];
const form = widget.length ? widget.closest("form") : $("form").first();
console.log(sitekey, Boolean(mamSrc)); // a MAM page needs a MAM_ tokencheerio का class selector पूरे class नामों से मैच करता है, इसलिए captchafox-wrapper जैसी class वाला कोई wrapper element गलती से नहीं चुना जाता। आख़िरी fallback render कॉल को inline पास की गई key पढ़ता है। जो key किसी bundled script फ़ाइल में रहती है, वह HTML में होती ही नहीं, और उसे ढूँढने का तरीका DevTools है। container न हो, तो कोड पेज का पहला फॉर्म ले लेता है। अगर पेज पर कोई search box या दूसरा फॉर्म भी है, तो इसके बजाय साइन-अप फॉर्म को उसकी id या उसके action से चुनें।
स्टेप 2: captchafox कॉल
Node.js में CaptchaFox हल करने के लिए आपको एक ही method चाहिए। यह sitekey, पेज URL और एक वैकल्पिक options object लेता है, और standard widget के लिए उसे बस पहले दो की ज़रूरत होती है।
import { CapSkip } from "capskip";
const solver = new CapSkip({ host: "127.0.0.1", port: 8080 });
// Copied from the script tag on MAM pages.
const MAM_PACKAGE = "https://s.uicdn.com/mampkg/@mamdev/core.frontend.libs.captchafox/";
const result = await solver.captchafox(sitekey, PAGE_URL, {
// undefined is dropped, so the standard widget sends nothing extra.
apiServer: mamSrc ? MAM_PACKAGE : undefined,
});
console.log(result.token.slice(0, 24)); // goes in cf-captcha-response
console.log(result.userAgent); // the browser that minted itresult.token और result.code में एक ही स्ट्रिंग होती है, और result.captchaId इस job के लिए CapSkip की id है। result.userAgent उस ब्राउज़र की पहचान है जिसने token बनाया, यानी CapSkip का अपना ब्राउज़र, न कि कोई चीज़ जो आपने भेजी हो। यह तभी सेट होता है जब solve ने कोई user agent रिपोर्ट किया हो, इसलिए इस्तेमाल करने से पहले इसे जाँच लें।
पेज URL वही पेज होना चाहिए जिस पर widget असल में चलता है। CaptchaFox हर key को अनुमत डोमेन की एक सूची के साथ रजिस्टर करता है और कुछ भी जारी करने से पहले host जाँचता है। किसी भी दूसरे डोमेन का पेज URL हर कोशिश पर मना कर दिया जाता है, इसलिए छोटा किया गया लिंक, सर्च रिज़ल्ट या किसी दूसरे डोमेन से आया redirect काम नहीं करेगा।
method जिन ऑप्शन को स्वीकार करता है
apiServer, api_server का alias है, यानी वह widget build जिसे हल करना है। यह method हर वह ऑप्शन हटा देता है जिसकी वैल्यू undefined या null हो, इसीलिए ऊपर वाली लाइन इसे हर कॉल पर पास कर सकती है। यह type और uri keys वाला एक proxy object भी लेता है, और useragent भी, जिसे स्वीकार तो किया जाता है पर जानबूझकर लागू नहीं किया जाता, क्योंकि CapSkip एक असली ब्राउज़र में उसकी अपनी पहचान के साथ हल करता है। सेकंड में दिया गया हर कॉल का अपना timeout उस एक solve के लिए क्लाइंट के recaptchaTimeout की जगह ले लेता है। पोलिंग की ऊपरी सीमा भी हर कॉल पर सेट की जा सकती है, लेकिन सिर्फ़ polling_interval के रूप में: camelCase वाला pollingInterval constructor का ऑप्शन है, और हर कॉल पर पास करने पर वह ValidationException फेंकता है। खाली sitekey या URL, कोई अनजान ऑप्शन, और HTTP, HTTPS, SOCKS5 या SOCKS5H के अलावा कोई proxy type भी ValidationException फेंकते हैं, और यह कोई भी रिक्वेस्ट आपकी मशीन से निकलने से पहले ही हो जाता है।
TypeScript में, बंडल किए गए types अब भी token को वैकल्पिक और ALTCHA के लिए बना हुआ बताते हैं, इसलिए strict mode में result.token पर non-null assertion चाहिए। हर CaptchaFox solve के लिए यह वैल्यू मौजूद होती है।
स्टेप 3: उसी user agent के साथ सबमिट करें जिसने token बनाया
Node.js में CaptchaFox हल करते समय यही वह स्टेप है जो तय करता है कि साइट token लेगी या नहीं। डिफ़ॉल्ट रूप से Node का fetch, Node 20 पर भी और Node 25 पर भी, ऐसा User-Agent header भेजता है जिसमें बस एक शब्द node होता है। यह वह ब्राउज़र नहीं है जिसने token बनाया, इसलिए लौटी हुई वैल्यू को उस रिक्वेस्ट पर कॉपी करें जो token ले जाती है:
// The form's own fields, hidden CSRF token included.
const body = new URLSearchParams(
form.serializeArray().map((f) => [f.name, f.value]),
);
body.set("email", "YOUR_EMAIL");
body.set("cf-captcha-response", result.token);
const headers = {
cookie: [...jar].map(([k, v]) => `${k}=${v}`).join("; "),
// Browsers send the page as Referer; strict servers want one.
referer: PAGE_URL,
};
// Without this line, fetch announces itself as user-agent: node.
if (result.userAgent) headers["user-agent"] = result.userAgent;
const res = await fetch(new URL(form.attr("action") || PAGE_URL, PAGE_URL), {
method: "POST",
headers,
body,
});
console.log(res.status);serializeArray वे सभी फ़ील्ड इकट्ठा करता है जो ब्राउज़र भेजता, छिपे हुए CSRF token और किसी भी टिक किए गए checkbox समेत, इसलिए आपको उनके नाम कभी नहीं लिखने पड़ते। यह submit बटन को छोड़ देता है, इसलिए अगर सर्वर बटन का नाम जाँचता है, तो उसे body.set से जोड़ें। Referer उतना ही मायने रखता है जितनी cookie। fetch न Referer भेजता है, न Origin, और कुछ frameworks, जिनमें Django भी है, ऐसी HTTPS फॉर्म पोस्ट ठुकरा देते हैं जिसमें दोनों में से कोई न हो, भले ही cookie और token सही हों।
दो और नियम इस बात से निकलते हैं कि CaptchaFox साइट की तरफ़ token की जाँच कैसे करता है। हर token एक ही बार और थोड़ी ही देर के लिए verify होता है, इसलिए तभी हल करें जब आप तैयार हों, और तुरंत सबमिट करें। और token को opaque मानें: उसे कभी न काटें, न दोबारा encode करें। कुछ साइटें उसे अपनी script से JSON बॉडी में भेजती हैं, इसलिए DevTools खोलकर फॉर्म को एक बार हाथ से सबमिट करें और पेज जो भेजता है, ठीक वैसा ही करें। CaptchaFox के getting started दस्तावेज़ widget का markup और सर्वर की तरफ़ होने वाली जाँच दिखाते हैं।
स्टेप 4: दोबारा कोशिश, challenge के प्रकार और timeout
CaptchaFox कौन सा challenge दिखाएगा, यह आप नहीं चुनते। ज़्यादातर solve में कुछ भी नहीं दिखता, क्योंकि ब्राउज़र से मिले संकेत अपने आप ही जाँच पास कर लेते हैं, और जब slide puzzle आता है, तो CapSkip आमतौर पर उसे पूरा कर देता है। Image-select और ऑडियो challenge दुर्लभ हैं और हल नहीं किए जाते: वे timeout के आख़िर में नहीं, बल्कि कुछ ही सेकंड में एक ApiException के रूप में लौटते हैं, जिसके मैसेज में ERROR_CAPTCHA_UNSOLVABLE होता है। नई कोशिश में आमतौर पर कुछ और आता है, इसलिए दोबारा कोशिश करना फ़ायदेमंद है, चाहे CapSkip में करें या अपने कोड में।
import { ApiException } from "capskip";
async function solveCaptchaFox(sitekey, url, options = {}, attempts = 3) {
for (let attempt = 1; ; attempt++) {
try {
return await solver.captchafox(sitekey, url, options);
} catch (err) {
// Select, audio and unreadable slide draws come back unsolvable;
// redraw. Anything else, such as a wrong API key, is final.
const redraw = err instanceof ApiException && err.message.includes("UNSOLVABLE");
if (!redraw || attempt === attempts) throw err;
}
}
}ApiException का मैसेज CapSkip का raw जवाब होता है, इसलिए यह जाँच error code को सीधे उसी से पढ़ लेती है। बस एक पेच है: जिस key को साइट मना कर देती है, जैसे गलत डोमेन पर, वह भी unsolvable के रूप में ही दिखती है, इसलिए उसे भी दोबारा आज़माया जाता है। वह हर कोशिश में कुछ ही सेकंड में फेल होती है और कभी कामयाब नहीं होती, और यही उसकी पहचान है। दूसरा तरीका CapSkip की सेटिंग्स में CaptchaFox वाली पंक्ति की Retries सेटिंग है। यह 0 से 3 तक की वैल्यू लेती है और डिफ़ॉल्ट रूप से 0 होती है। तब CapSkip बिना सपोर्ट वाले challenges, समय खत्म हो चुकी कोशिशों और ब्राउज़र errors पर अपने आप दोबारा कोशिश करता है, लेकिन मना की गई key पर कभी नहीं।
captchafox क्लाइंट के recaptchaTimeout पर पोलिंग करता है, जो डिफ़ॉल्ट रूप से 300 सेकंड है, क्योंकि यह एक असली ब्राउज़र session है। CapSkip की अपनी समय सीमाएँ भी होती हैं: कोई टास्क 10 CaptchaFox threads (Max. Threads) में से किसी एक के लिए 250 सेकंड (Wait Timeout) तक इंतज़ार कर सकता है, और एक कोशिश को 150 सेकंड (Row Timeout) मिलते हैं। कोई thread खाली हो, तो फेल हुई कोशिश SDK के 300 सेकंड पूरे होने से काफ़ी पहले ही ApiException के रूप में आप तक पहुँच जाती है। लंबी queue के बाद SDK पहले अपनी सीमा तक पहुँच सकता है और TimeoutException फेंक सकता है, जबकि CapSkip अभी भी काम कर रहा होता है। इसलिए जब आप कई solve queue में डालें या Retries बढ़ाएँ, तो लंबा timeout पास करें, क्योंकि हर दोबारा कोशिश एक और Row Timeout जोड़ सकती है। SDK connection errors के दौरान भी पोलिंग जारी रखता है, इसलिए अगर CapSkip solve के बीच में रुक जाए, तो कॉल NetworkException पर नहीं, TimeoutException पर खत्म होती है।
पूरा चलने वाला उदाहरण
यह रहा पूरा रन, एक ही फ़ाइल में। signUp पेज fetch करता है, key पढ़ता है, दोबारा कोशिशों के साथ हल करता है, और फॉर्म को उसकी cookies, एक Referer और token बनाने वाले ब्राउज़र के user agent के साथ पोस्ट करता है।
// npm install capskip cheerio
// signup.mjs: run with node signup.mjs
import * as cheerio from "cheerio";
import {
CapSkip, ApiException, CapSkipError, TimeoutException, ValidationException,
} from "capskip";
const PAGE_URL = "https://example.com/signup";
// Copied from the script tag on MAM pages.
const MAM_PACKAGE = "https://s.uicdn.com/mampkg/@mamdev/core.frontend.libs.captchafox/";
const solver = new CapSkip({
apiKey: process.env.CAPSKIP_API_KEY ?? "capskip",
host: process.env.CAPSKIP_HOST ?? "127.0.0.1",
port: Number(process.env.CAPSKIP_PORT ?? 8080),
});
async function solveCaptchaFox(sitekey, url, options = {}, attempts = 3) {
for (let attempt = 1; ; attempt++) {
try {
return await solver.captchafox(sitekey, url, options);
} catch (err) {
// Select, audio and unreadable slide draws come back unsolvable.
const redraw = err instanceof ApiException && err.message.includes("UNSOLVABLE");
if (!redraw || attempt === attempts) throw err;
console.log(`attempt ${attempt}: ${err.message}`);
}
}
}
async function signUp(pageUrl, email) {
// One jar per run, so runs side by side never share a session.
const jar = new Map();
const page = await fetch(pageUrl);
for (const line of page.headers.getSetCookie()) {
const pair = line.split(";")[0];
const eq = pair.indexOf("=");
jar.set(pair.slice(0, eq).trim(), pair.slice(eq + 1).trim());
}
const html = await page.text();
const $ = cheerio.load(html);
const widget = $(".captchafox").first();
const mamSrc = $('script[src*="mampkg/@mamdev/core.frontend.libs.captchafox"]').attr("src");
const sitekey = widget.attr("data-sitekey")
?? (mamSrc && new URL(mamSrc, pageUrl).searchParams.get("key"))
?? html.match(/captchafox\.render\([\s\S]{0,300}?sitekey\s*:\s*["']([^"']+)/)?.[1];
if (!sitekey) throw new Error("No sitekey in the HTML; find it in DevTools.");
const form = widget.length ? widget.closest("form") : $("form").first();
const result = await solveCaptchaFox(sitekey, pageUrl, {
apiServer: mamSrc ? MAM_PACKAGE : undefined,
});
const body = new URLSearchParams(form.serializeArray().map((f) => [f.name, f.value]));
body.set("email", email);
body.set("cf-captcha-response", result.token);
const headers = {
cookie: [...jar].map(([k, v]) => `${k}=${v}`).join("; "),
referer: pageUrl,
};
if (result.userAgent) headers["user-agent"] = result.userAgent;
const action = new URL(form.attr("action") || pageUrl, pageUrl);
return fetch(action, { method: "POST", headers, body });
}
try {
const res = await signUp(PAGE_URL, "YOUR_EMAIL");
console.log(res.status, (await res.text()).slice(0, 80));
} catch (err) {
if (err instanceof ValidationException) console.error(`not sent: ${err.message}`);
else if (err instanceof TimeoutException) console.error("gave up after recaptchaTimeout");
else if (err instanceof CapSkipError) console.error(`solve failed: ${err.name}: ${err.message}`);
else throw err;
process.exitCode = 1;
}अगर हर रन कुछ ही सेकंड में फेल हो जाए, तो सबसे पहले पेज URL जाँचें, क्योंकि अपने रजिस्टर्ड डोमेन के बाहर इस्तेमाल हुई key हर बार एक ही तरह फेल होती है। अगर sitekey वाली जाँच error फेंकती है, तो पेज widget को किसी bundled script से बनाता है, और key Network टैब में होती है, जैसा स्टेप 1 में बताया गया है। इस method के पीछे का raw endpoint यहाँ दर्ज है: API रेफ़रेंस का CaptchaFox सेक्शन.
एक साथ कई साइन-अप चलाना
Node में CapSkip का हर method एक Promise लौटाता है, और AsyncCapSkip उसी class का बस दूसरा नाम है, इसलिए कई solve साथ-साथ चलाना सीधा-सादा JavaScript है। आपको बस एक सीमा चाहिए। CapSkip डिफ़ॉल्ट रूप से एक साथ 10 CaptchaFox solve चलाता है और बाकी को किसी खाली thread के लिए इंतज़ार कराता है, इसलिए एक छोटा pool, जो एक समय में दस solve चालू रखे, उससे मेल खाता है। इसे पूरे उदाहरण के आख़िर वाले try block की जगह रखें:
// At most `limit` calls in flight; a failure becomes that item's Error.
async function mapLimited(items, limit, fn) {
const results = new Array(items.length);
let next = 0;
async function worker() {
while (next < items.length) {
const i = next++;
results[i] = await fn(items[i]).catch((err) => err);
}
}
await Promise.all(Array.from({ length: Math.min(limit, items.length) }, worker));
return results;
}
const emails = ["YOUR_EMAIL_1", "YOUR_EMAIL_2", "YOUR_EMAIL_3"];
const results = await mapLimited(emails, 10, (email) => signUp(PAGE_URL, email));
for (const r of results) console.log(r instanceof Error ? r.message : r.status);signUp पूरे उदाहरण वाला function है। यह हर कॉल पर अपना अलग cookie jar बनाता है, और इसी वजह से parallel में सुरक्षित है: दस रन में साझा किया गया एक ही jar उनके sessions और CSRF tokens को आपस में मिला देगा। यह हर token को पोस्ट जाने तक उसके अपने user agent के साथ भी रखता है। बड़े pool के लिए CapSkip की CaptchaFox सेटिंग्स में Max. Threads बढ़ाएँ। CaptchaFox ब्राउज़र के साथ-साथ नेटवर्क को भी स्कोर करता है, इसलिए लंबे रन में एक ही पते से बहुत सारे solve challenge की दर बढ़ा देते हैं। उसी पंक्ति में Configure Proxies बटन से प्रॉक्सी सेट करें, या हर कॉल पर एक proxy object पास करें।
सॉल्वर को किसी दूसरी मशीन पर चलाना
जब तक script और CapSkip एक ही Windows PC पर हों, 127.0.0.1 सही है। जैसे ही Node कोड किसी VPS, कंटेनर, CI runner या serverless function पर जाता है, loopback गलत मशीन की ओर इशारा करता है और पहला ही solve ECONNREFUSED के साथ NetworkException फेंकता है। CapSkip को Server मोड पर कर दें और वह आपके नेटवर्क पते या पब्लिक IP पर सुनने लगता है, ताकि इनमें से कोई भी उसी API के ज़रिए उसे कॉल कर सके। जब रास्ता इंटरनेट से होकर जाए तो स्टैटिक पब्लिक IP इस्तेमाल करें, API key validation चालू करें, और Windows Firewall नियम से पोर्ट को सिर्फ़ अपेक्षित पतों तक सीमित रखें। सॉल्वर अब भी आपकी अपनी Windows मशीन है, और solve अब भी बिना मीटर वाले हैं।
क्लाइंट एनवायरनमेंट वेरिएबल खुद नहीं पढ़ता। CAPSKIP_HOST, CAPSKIP_PORT और CAPSKIP_API_KEY को अपने कोड में पढ़ें और उन्हें constructor को पास करें, जैसा पूरा उदाहरण करता है, ताकि वही script आपकी डेस्क पर भी चले और सर्वर पर भी।
आम errors और उनका मतलब
| आप जो देखते हैं | कारण | फिक्स |
|---|---|---|
| साइट उस token को ठुकरा देती है जिसे CapSkip ने हल हुआ बताकर लौटाया था | पोस्ट user-agent: node के साथ गई, जो fetch का डिफ़ॉल्ट है, उस ब्राउज़र के रूप में नहीं जिसने token बनाया था | उस रिक्वेस्ट पर result.userAgent को User-Agent header के रूप में भेजें |
| user agent मेल खाने के बावजूद ठुकराया गया | पेज MAM पैकेज लोड करता है और solve में डिफ़ॉल्ट widget इस्तेमाल हुआ, या इसका उल्टा | script टैग पढ़ें और apiServer को उसके मुताबिक़ सेट करें |
| सही token और user agent के बावजूद पोस्ट पर 403 | session cookie नहीं भेजी गई, इसलिए CSRF फ़ील्ड अब मेल नहीं खाता, या पोस्ट में Referer नहीं था | पेज fetch से मिली cookies साथ भेजें, और पेज URL को Referer के रूप में भेजें |
| result.userAgent का मान undefined है | solve ने कोई user agent रिपोर्ट नहीं किया, इसलिए fetch अपना user agent भेजता है | if वाली जाँच रहने दें; अगर साइट node को मना करती है, तो किसी मौजूदा desktop ब्राउज़र का user agent खुद भेजें |
| एक ही 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 हल करें, और तुरंत पोस्ट करें |
| कुछ भी भेजे जाने से पहले ही ValidationException | खाली sitekey या URL, कोई ऐसा ऑप्शन जो यह method नहीं लेता, जैसे हर कॉल पर दिया गया pollingInterval, या कोई ऐसा proxy type जिसे CapSkip स्वीकार नहीं करता | जाँचें कि sitekey मिली थी, और संदेश में बताए गए ऑप्शन को ठीक करें या हटा दें |
| पाँच मिनट बाद TimeoutException | किसी खाली CaptchaFox thread का इंतज़ार और खुद solve, दोनों मिलकर SDK के 300 सेकंड से आगे निकल गए, या CapSkip solve के बीच में रुक गया | pool को Max. Threads तक सीमित रखें, या उस कॉल के लिए लंबा timeout पास करें |
| पहली कॉल पर ECONNREFUSED या ETIMEDOUT के साथ NetworkException | CapSkip चल नहीं रहा, host या port गलत है, या कोई फ़ायरवॉल कनेक्शन ड्रॉप कर देता है | CapSkip शुरू करें, फिर देखें कि उसे Local मोड में होना चाहिए या Server मोड में |
FAQ
क्या axios या got से user agent वाली समस्या टल जाती है?
नहीं। वे बस नाम बदल देते हैं। axios, axios और उसके बाद अपना वर्ज़न नंबर भेजता है, और got, got और उसके बाद अपनी GitHub repository का पता भेजता है। जब तक आप इन्हें ऐसा करने के लिए सेट न करें, दोनों में से कोई भी न cookies रखता है, न Referer भेजता है, इसलिए वही तीन headers यहाँ भी लागू होते हैं। क्लाइंट चाहे जो हो, token ले जाने वाली रिक्वेस्ट पर user agent को result.userAgent से सेट करें।
क्या मैं token को इसके बजाय Puppeteer या Playwright में इस्तेमाल कर सकता हूँ?
हाँ, बशर्ते उसे सबमिट करने वाला पेज उसी user agent के साथ चले जो CapSkip ने लौटाया। पहले हल करें, फिर browser.newContext({ userAgent: ua }) से Playwright context खोलें, या Puppeteer में पेज लोड होने से पहले page.setUserAgent(ua) कॉल करें। फॉर्म लोड करें, token को cf-captcha-response फ़ील्ड में लिखें और सबमिट करें। अगर आपके ऑटोमेशन को किसी और काम के लिए ब्राउज़र की ज़रूरत नहीं है, तो ऊपर वाला fetch तरीका ज़्यादा हल्का है।
यह Python वर्ज़न से कैसे अलग है?
कॉल और नियम वही हैं, और मुख्य जाल भी वही है: HTTP क्लाइंट user agent के रूप में अपना ही नाम भेजता है। Python में वह नाम python-requests या python-httpx होता है, और requests.Session आपके लिए cookies रखता है। Node में वह node होता है, और cookies आपको खुद संभालनी पड़ती हैं। Python वाला पहलू यहाँ कवर किया गया है: Python में CaptchaFox हल करने की गाइड.
संक्षेप में
Node.js में CaptchaFox हल करने के लिए, पेज fetch करें और उसकी cookies रखें, sitekey को captchafox container, render कॉल या MAM script से पढ़ें, और ध्यान दें कि पेज कौन सा build लोड करता है। solver.captchafox() को sitekey और असली पेज URL के साथ कॉल करें, और apiServer सिर्फ़ MAM पेजों के लिए जोड़ें। result.token को cf-captcha-response में पोस्ट करें, पेज की cookies, Referer के रूप में पेज, और User-Agent header के रूप में result.userAgent के साथ, एक बार और तुरंत। unsolvable challenge आने पर दोबारा कोशिश करें, एक समय में Max. Threads (डिफ़ॉल्ट रूप से 10) से ज़्यादा solve न चलाएँ, और जैसे ही script सॉल्वर की मशीन से बाहर जाए, Server मोड पर चले जाएँ।
- CaptchaFox कैसे काम करता है और सॉल्वर क्या-क्या कवर करता है: CaptchaFox सॉल्वर पेज.
- कैप्चा के वे सभी टाइप जिन्हें Node.js पैकेज संभालता है: Node.js कैप्चा सॉल्वर पेज.
इस टाइप में दोबारा कोशिश का मतलब आमतौर पर बस नया challenge निकलवाना होता है, और अपनी ही मशीन पर चलने वाले असीमित कैप्चा सॉल्वर के साथ हर नया challenge बस कुछ सेकंड लेता है, किसी और बिल किए गए solve का ख़र्च नहीं।
