Cloudflare Turnstile birçok sitede reCAPTCHA'nın yerini alıyor. Bu kılavuz Node.js akışının tamamını kapsar: Turnstileyi tespit edin, site anahtarını çıkarın, CaptchaAI aracılığıyla çözün ve jetonu gönderin.
Önkoşullar
- Node.js 18+ (yerel getirme)
- CaptchaAI API anahtarı
1. Adım: Site anahtarını tespit edin ve çıkarın
async function extractTurnstileSitekey(url) {
const resp = await fetch(url, {
headers: {
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36",
},
});
const html = await resp.text();
// Method 1: data-sitekey attribute on Turnstile div
const divMatch = html.match(
/class=["'][^"]*cf-turnstile[^"]*["'][^>]*data-sitekey=["']([0-9x][A-Za-z0-9_-]+)["']/
);
if (divMatch) return divMatch[1];
// Method 2: data-sitekey on any element (Turnstile keys start with 0x)
const attrMatch = html.match(
/data-sitekey=["'](0x[A-Za-z0-9_-]+)["']/
);
if (attrMatch) return attrMatch[1];
// Method 3: In JavaScript turnstile.render call
const jsMatch = html.match(
/turnstile\.render\s*\([^,]+,\s*\{[^}]*sitekey\s*:\s*["']([0-9x][A-Za-z0-9_-]+)["']/
);
if (jsMatch) return jsMatch[1];
// Method 4: Generic sitekey in inline script
const inlineMatch = html.match(
/sitekey\s*:\s*["'](0x[A-Za-z0-9_-]+)["']/
);
if (inlineMatch) return inlineMatch[1];
return null;
}
Adım 2: Turnstileyi CaptchaAI ile çözün
const API_KEY = "YOUR_API_KEY";
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function solveTurnstile(sitekey, pageurl, action = null) {
// Submit task
const submitData = {
key: API_KEY,
method: "turnstile",
sitekey: sitekey,
pageurl: pageurl,
json: "1",
};
if (action) {
submitData.action = action;
}
const submitResp = await fetch("https://ocr.captchaai.com/in.php", {
method: "POST",
body: new URLSearchParams(submitData),
});
const submitResult = await submitResp.json();
if (submitResult.status !== 1) {
throw new Error(`Submit error: ${submitResult.request}`);
}
const taskId = submitResult.request;
console.log(`Task ID: ${taskId}`);
// Poll for result
for (let i = 0; i < 30; i++) {
await sleep(5000);
const pollResp = await fetch(
`https://ocr.captchaai.com/res.php?${new URLSearchParams({
key: API_KEY,
action: "get",
id: taskId,
json: "1",
})}`
);
const pollResult = await pollResp.json();
if (pollResult.status === 1) {
return pollResult.request;
}
if (pollResult.request === "ERROR_CAPTCHA_UNSOLVABLE") {
throw new Error("Turnstile unsolvable");
}
}
throw new Error("Solve timed out");
}
3. Adım: Belirteci gönderin
async function submitTurnstileForm(url, formData, token) {
const body = new URLSearchParams({
...formData,
"cf-turnstile-response": token,
});
const resp = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36",
},
body,
});
return {
status: resp.status,
body: await resp.text(),
};
}
Giriş akışını tamamlayın
async function loginWithTurnstile(loginUrl, credentials) {
// Step 1: Extract sitekey
const sitekey = await extractTurnstileSitekey(loginUrl);
if (!sitekey) {
throw new Error("Turnstile sitekey not found");
}
console.log(`Sitekey: ${sitekey}`);
// Step 2: Solve Turnstile
const token = await solveTurnstile(sitekey, loginUrl);
console.log(`Token: ${token.substring(0, 50)}...`);
// Step 3: Submit form
const result = await submitTurnstileForm(loginUrl, credentials, token);
console.log(`Result: ${result.status}`);
return result;
}
// Usage
const result = await loginWithTurnstile("https://staging.example.com/qa-login", {
email: "user@example.com",
password: "pass123",
});
Üretim çözücü sınıfı
class TurnstileSolver {
#apiKey;
constructor(apiKey) {
this.#apiKey = apiKey;
}
async solve(sitekey, pageurl, options = {}) {
const taskId = await this.#submit(sitekey, pageurl, options);
return await this.#poll(taskId);
}
async detectAndSolve(url) {
const sitekey = await this.#detect(url);
if (!sitekey) throw new Error("No Turnstile found");
return await this.solve(sitekey, url);
}
async #detect(url) {
const resp = await fetch(url, {
headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0" },
});
const html = await resp.text();
const match = html.match(/data-sitekey=["'](0x[A-Za-z0-9_-]+)["']/);
return match ? match[1] : null;
}
async #submit(sitekey, pageurl, options) {
const body = new URLSearchParams({
key: this.#apiKey,
method: "turnstile",
sitekey,
pageurl,
json: "1",
...(options.action && { action: options.action }),
...(options.cdata && { data: options.cdata }),
});
const resp = await fetch("https://ocr.captchaai.com/in.php", {
method: "POST",
body,
});
const data = await resp.json();
if (data.status !== 1) throw new Error(`Submit: ${data.request}`);
return data.request;
}
async #poll(taskId) {
const params = new URLSearchParams({
key: this.#apiKey,
action: "get",
id: taskId,
json: "1",
});
for (let i = 0; i < 30; i++) {
await new Promise((r) => setTimeout(r, 5000));
const resp = await fetch(`https://ocr.captchaai.com/res.php?${params}`);
const data = await resp.json();
if (data.status === 1) return data.request;
if (data.request === "ERROR_CAPTCHA_UNSOLVABLE") {
throw new Error("Unsolvable");
}
}
throw new Error("Timed out");
}
}
// Usage
const solver = new TurnstileSolver("YOUR_API_KEY");
const token = await solver.detectAndSolve("https://staging.example.com/qa-login");
Aksiyon ve cData parametreleriyle Turnstile
Bazı Turnstile uygulamaları action ve cData parametrelerini içerir:
// Extract action from the page
function extractTurnstileAction(html) {
const match = html.match(
/data-action=["']([^"']+)["']|action\s*:\s*["']([^"']+)["']/
);
return match ? match[1] || match[2] : null;
}
// Solve with action
const token = await solver.solve(sitekey, pageurl, {
action: "login",
cdata: "session_abc123",
});
Sunucu tarafı jeton doğrulaması
Turnstile jetonlarını doğrulayan bir sunucu oluşturuyorsanız:
async function verifyTurnstileToken(token, ip) {
const resp = await fetch(
"https://challenges.cloudflare.com/turnstile/v0/siteverify",
{
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
secret: "YOUR_TURNSTILE_SECRET_KEY",
response: token,
remoteip: ip,
}),
}
);
const data = await resp.json();
return data.success;
}
Sorun giderme
| Belirti | Sebep | Düzeltme |
|---|---|---|
Site anahtarı 6Le ile başlar |
Bu Turnstile değil, reCAPTCHA | method=userrecaptcha'yi kullanın |
| Jeton reddedildi | Yanlış site anahtarı veya süresi dolmuş | Site anahtarını yeniden çıkarın, daha hızlı gönderin |
| Site anahtarı bulunamadı | Turnstile JavaScript aracılığıyla yüklendi | Bunun yerine Puppeteer/Playwright kullanın |
ERROR_BAD_PARAMETERS |
Eksik site anahtarı veya sayfa url'si | Her ikisinin de mevcut olup olmadığını kontrol edin |
| Gönderimden sonra 403 yanıtı | Başlıklarda bot tespiti | Gerçekçi Kullanıcı Aracısı kullanın |
Sık sorulan sorular
Turnstilenin reCAPTCHA'dan farkı nedir?
Turnstile, Cloudflare'in CAPTCHA'sının alternatifidir. Genellikle görünmezdir, çözülmesi daha hızlıdır ve method=userrecaptcha yerine method=turnstile API parametresini kullanır.
Eylem parametresini belirtmem gerekiyor mu?
Yalnızca sitenin Turnstile uygulaması bunu kullanıyorsa. HTML'de data-action'yi veya JavaScript'te action:'yi kontrol edin.
Turnstile çözmenin başarı oranı nedir?
CaptchaAI, Turnstile zorluklarında %100 başarı oranına ulaşıyor.
Özet
Cloudflare Turnstile'yi Node.js ile çözün veCaptchaAI: site anahtarını çıkarın (0x ile başlar), method=turnstile API aracılığıyla çözün ve belirteci cf-turnstile-response olarak gönderin.