Sunucu tarafında CAPTCHA çözmek için tam bir tarayıcı ayağa kaldırmak çoğu zaman iş yükünüzün en pahalı ve en kırılgan parçasıdır. İyi haber şu: reCAPTCHA, Turnstile ve resim CAPTCHA'larını yalnızca Axios ve birkaç saf HTTP isteğiyle çözebilirsiniz — ne Puppeteer, ne Playwright, ne de headless tarayıcı yükü. CaptchaAI çözümü uzaktan üretir; siz yalnızca dönen token'ı alıp formunuza yerleştirirsiniz.
Bu rehber, Node.js için yeniden kullanılabilir bir CaptchaAI istemcisi kurar, ardından reCAPTCHA v2'den Turnstile'a ve resim CAPTCHA'larına kadar her türü aynı istemciyle çözer. Tüm örnekler çalışan koddur ve doğrudan iş akışınıza kopyalanabilir.
Tarayıcısız çözüm neden daha hafif?
Bir headless tarayıcı örneği tipik olarak 200-500 MB RAM tüketir; aynı işi saf HTTP ile yapan CaptchaAI istemcisi ise yaklaşık 5 MB ile yetinir. Sunucu tarafı otomasyonda bu, örnek başına 40-100 kat daha az bellek demektir — ve konteyner başına çok daha fazla eşzamanlı iş demektir.
Fiyatlandırma modeli de bu yaklaşımı ödüllendirir. CaptchaAI çözüm başına değil, eşzamanlı thread başına ücretlendirir ve her planda thread başına sınırsız çözüm vardır. En düşük plan olan BASIC ($15/ay, 5 thread) aynı anda beş CAPTCHA'yı işleme kapasitesi verir; hacim büyüdükçe STANDARD ($30/ay, 15 thread) veya ADVANCE ($90/ay, 50 thread) planlarına geçebilirsiniz. Ücretlendirme USD üzerinden ve aylık sabittir — TL kur oynaklığından etkilenmeyen öngörülebilir bir gider kalemi, freelance otomasyon işi yapan geliştiriciler için pratik bir avantajdır.
Başlamadan önce gerekenler
| Gereksinim | Ayrıntılar |
|---|---|
| Node.js | 16+ |
| axios | 1.x |
| CaptchaAI API anahtarı | Ücretsiz API anahtarı alın |
Tek harici bağımlılık Axios'tur. Kazıma örneği için ayrıca cheerio kullanacağız, ama çekirdek çözüm akışı yalnızca Axios ile çalışır.
npm install axios
Yeniden kullanılabilir CaptchaAI istemcisi
Aşağıdaki sınıf tüm mantığı tek yerde toplar. submit metodu görevi in.php uç noktasına gönderir ve bir görev kimliği döndürür; poll metodu res.php uç noktasını beş saniyede bir sorgulayarak sonucu bekler; solve ise ikisini tek çağrıda birleştirir. Varsayılan zaman aşımı 300.000 ms'dir (5 dakika) ve getBalance ile hesap bakiyenizi kontrol edebilirsiniz.
Bu istemciyi captchaai.js olarak kaydedin ve tüm örneklerde yeniden kullanın:
const axios = require("axios");
class CaptchaAI {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = "https://ocr.captchaai.com";
}
async submit(params) {
params.key = this.apiKey;
const resp = await axios.get(`${this.baseUrl}/in.php`, { params });
const text = resp.data;
if (!String(text).startsWith("OK|")) {
throw new Error(`Submit failed: ${text}`);
}
return String(text).split("|")[1];
}
async poll(taskId, timeoutMs = 300000) {
const deadline = Date.now() + timeoutMs;
const params = { key: this.apiKey, action: "get", id: taskId };
while (Date.now() < deadline) {
await new Promise((r) => setTimeout(r, 5000));
const resp = await axios.get(`${this.baseUrl}/res.php`, { params });
const text = String(resp.data);
if (text === "CAPCHA_NOT_READY") continue;
if (text.startsWith("OK|")) return text.split("|").slice(1).join("|");
throw new Error(`Solve failed: ${text}`);
}
throw new Error(`Timeout after ${timeoutMs}ms for task ${taskId}`);
}
async solve(params, timeoutMs = 300000) {
const taskId = await this.submit(params);
return this.poll(taskId, timeoutMs);
}
async getBalance() {
const resp = await axios.get(`${this.baseUrl}/res.php`, {
params: { key: this.apiKey, action: "getbalance" },
});
return parseFloat(resp.data);
}
}
module.exports = CaptchaAI;
reCAPTCHA v2'yi tarayıcı olmadan çözün
En yaygın senaryo reCAPTCHA v2'dir. googlekey alanına sayfanın sitekey değerini, pageurl alanına da CAPTCHA'nın göründüğü URL'yi verirsiniz. Dönen token'ı formun g-recaptcha-response alanına yerleştirip yine Axios ile gönderirsiniz — hiçbir noktada tarayıcı açılmaz.
const CaptchaAI = require("./captchaai");
async function main() {
const solver = new CaptchaAI(process.env.CAPTCHAAI_API_KEY);
// Solve the CAPTCHA without opening any browser
const token = await solver.solve({
method: "userrecaptcha",
googlekey: "6Le-wvkS...",
pageurl: "https://staging.example.com/qa-login",
});
// Submit form with the token using Axios
const resp = await axios.post("https://staging.example.com/qa-login", {
username: "user",
password: "pass",
"g-recaptcha-response": token,
});
console.log(`Login response: ${resp.status}`);
}
main().catch(console.error);
Cloudflare Turnstile'ı çözün
Turnstile için yalnızca method değerini turnstile yapıp sitekey ve pageurl vermeniz yeterlidir. Bu kez dönen token, formun cf-turnstile-response alanına gider. Token alanının adı türden türe değişir; reCAPTCHA'nın g-recaptcha-response alanıyla karıştırmayın.
const token = await solver.solve({
method: "turnstile",
sitekey: "0x4AAAAA...",
pageurl: "https://example.com",
});
// Submit with Turnstile token
const resp = await axios.post("https://example.com/api/verify", {
"cf-turnstile-response": token,
data: "payload",
});
Resim (image) CAPTCHA'larını çözün
Klasik metin tabanlı resim CAPTCHA'ları için görüntüyü base64'e çevirip method: "base64" ile gönderirsiniz. Bu sefer yanıt bir token değil, doğrudan çözülmüş metindir ve onu formun ilgili alanına koyarsınız.
const fs = require("fs");
const imageBuffer = fs.readFileSync("captcha.png");
const imageB64 = imageBuffer.toString("base64");
const text = await solver.solve({
method: "base64",
body: imageB64,
});
console.log(`CAPTCHA text: ${text}`);
// Submit form with solved text
const resp = await axios.post("https://example.com/verify", {
captcha: text,
other_data: "value",
});
Uçtan uca kazıma akışı
Gerçek dünyada sitekey'i çoğu zaman elle bilmezsiniz; sayfanın HTML'inden okumanız gerekir. Aşağıdaki akış sayfayı çeker, cheerio ile sitekey'i çıkarır, CAPTCHA'yı çözer ve formu tüm gizli alanlarıyla birlikte gönderir. Bir e-ticaret ekibinin staging ortamında ödeme (checkout) akışını otomatik test etmesi tam da bu desenle çalışır.
Not: kazıdığınız veri kişisel veri içeriyorsa Türkiye'de KVKK kapsamına girer. Bu tür akışları yalnızca yetkili olduğunuz QA ve veri toplama senaryolarında, kendi staging ortamınızda çalıştırın.
const CaptchaAI = require("./captchaai");
const axios = require("axios");
const cheerio = require("cheerio");
async function scrapeProtectedPage(url) {
const solver = new CaptchaAI(process.env.CAPTCHAAI_API_KEY);
// Step 1: Fetch the page
const page = await axios.get(url);
const $ = cheerio.load(page.data);
// Step 2: Extract the reCAPTCHA site key
const siteKey = $(".g-recaptcha").attr("data-sitekey");
if (!siteKey) {
console.log("No CAPTCHA found, returning page content");
return page.data;
}
// Step 3: Solve the CAPTCHA
console.log(`Solving CAPTCHA for ${url}...`);
const token = await solver.solve({
method: "userrecaptcha",
googlekey: siteKey,
pageurl: url,
});
// Step 4: Submit form with token
const formAction = $("form").attr("action") || url;
const formData = {};
$("form input").each((_, el) => {
const name = $(el).attr("name");
const value = $(el).attr("value") || "";
if (name) formData[name] = value;
});
formData["g-recaptcha-response"] = token;
const result = await axios.post(formAction, new URLSearchParams(formData), {
headers: { "Content-Type": "application/x-www-form-urlencoded" },
});
return result.data;
}
scrapeProtectedPage("https://example.com/data")
.then((data) => console.log("Success:", typeof data))
.catch(console.error);
Toplu ve eşzamanlı çözüm
Tarayıcısız yaklaşımın en büyük kazancı burada görünür: yaklaşım hafif olduğu için yüzlerce isteği tek makinede paralel çalıştırabilirsiniz. Eşzamanlılığın üst sınırını planınızın thread sayısı belirler — BASIC ile 5, ADVANCE ile 50 CAPTCHA aynı anda işlenir. Promise.all ile toplu gönderim yaparken hata yönetimini her görev için ayrı tutun ki tek bir başarısızlık toptan çökmesin.
async function solveBatch(urls, siteKey) {
const solver = new CaptchaAI(process.env.CAPTCHAAI_API_KEY);
const promises = urls.map(async (url) => {
try {
const token = await solver.solve({
method: "userrecaptcha",
googlekey: siteKey,
pageurl: url,
});
return { url, token, error: null };
} catch (error) {
return { url, token: null, error: error.message };
}
});
const results = await Promise.all(promises);
const solved = results.filter((r) => r.token);
console.log(`Solved ${solved.length}/${urls.length}`);
return results;
}
Sık karşılaşılan hatalar ve çözümleri
Üretimde en çok görülen dört durum ve pratik çözümleri aşağıda. Token satırındaki en kritik nokta: token'ın kısa bir ömrü vardır, bu yüzden çözümden hemen sonra göndermelisiniz.
| Hata | Sebep | Düzeltme |
|---|---|---|
AxiosError: getaddrinfo ENOTFOUND |
DNS sorunu | Ağ bağlantısını kontrol edin |
Submit failed: ERROR_WRONG_USER_KEY |
Geçersiz API anahtarı | Anahtarı kontrol panelinden doğrulayın |
Submit failed: ERROR_ZERO_BALANCE |
Bakiye yok | Hesaba bakiye ekleyin |
| Token hedef site tarafından reddedildi | Token'ın süresi doldu | Token'ı 60 saniye içinde gönderin |
Sık sorulan sorular
Axios ile hangi CAPTCHA türlerini çözebilirim?
reCAPTCHA v2 ve v3, Cloudflare Turnstile ve metin tabanlı resim CAPTCHA'larını bu istemciyle çözebilirsiniz. hCaptcha ve FunCaptcha ise CaptchaAI tarafından desteklenmiyor; bu türleri çözdüğünü iddia eden hiçbir örneğe güvenmeyin.
CaptchaAI hCaptcha veya FunCaptcha'yı destekliyor mu?
Hayır. Her ikisi de şu an desteklenmiyor. GeeTest v4 için ise yalnızca "çok yakında" durumu geçerlidir; mevcut değildir.
Eşzamanlı olarak kaç CAPTCHA çözebilirim?
Aynı anda işlenen CAPTCHA sayısı planınızın thread sayısına bağlıdır: BASIC ($15/ay, 5 thread) beş, ADVANCE ($90/ay, 50 thread) elli eşzamanlı çözüm sağlar. Thread başına çözüm sınırı yoktur.
Axios yerine fetch kullanabilir miyim?
Evet. Node.js 18+ yerleşik fetch'i içerir ve CaptchaAI API parametreleri birebir aynıdır. Tek fark isteklerin nasıl yazıldığıdır; çözüm akışı değişmez.
Token neden hedef site tarafından reddedildi?
En yaygın neden token'ın süresinin dolmasıdır. Çözümden sonra token'ı genellikle 60 saniye içinde göndermelisiniz ve pageurl çözüm anında verdiğiniz URL ile aynı olmalıdır.