CaptchaAI bir ızgara CAPTCHA'yı çözdüğünde size tıklanması gereken hücrelerin indekslerini döndürür — örneğin [1, 3, 6, 9]. Asıl iş bundan sonra başlar: bu numaraları tarayıcıda gerçek piksel tıklamalarına çevirmek. reCAPTCHA v2 görüntü zorlukları gibi ızgaralar 3×3 veya 4×4 gelir ve "Trafik ışığı olan tüm kareleri seçin" tarzı bir talimat gösterir. Bu rehber ızgarayı yakalamayı, indeksleri koordinatlara haritalamayı ve doğru döşemelere tıklamayı sırasıyla ele alır.
Bu akış, form ve ödeme adımı yoğun Türk e-ticaret ve fintech sitelerinin QA testlerinde sık karşınıza çıkar.
Sırasıyla dört adımı uygulayacağız:
- Izgarayı yakalama: challenge iframe'ine geçip görseli ve talimat metnini alın.
- CaptchaAI'ye gönderme: base64 görseli
in.php'ye yollayın, sonucures.phpüzerinden sorgulayın. - Indeks → koordinat: dönen hücre indekslerini piksel merkezlerine çevirin.
- Tıklama ve doğrulama: hesaplanan koordinatlara tıklayıp doğrula düğmesine basın.
Izgara boyutları ve hücre numaralandırması
CAPTCHA'lar iki standart ızgara boyutu kullanır:
3×3 Grid: 4×4 Grid:
1 2 3 1 2 3 4
4 5 6 5 6 7 8
7 8 9 9 10 11 12
13 14 15 16
Hücreler soldan sağa, yukarıdan aşağıya numaralandırılır; bu sıra, CaptchaAI indekslerinin temelidir.
Neden numaralandırma sırası önemli?
Bu numaralandırma sözleşmesi kritiktir: CaptchaAI [1, 3, 6, 9] gibi bir dizi döndürdüğünde bu sayılar tam olarak yukarıdaki şemadaki konumlara karşılık gelir. Sıralamayı yanlış varsayarsanız doğru döşemeleri değil komşularını tıklarsınız. Bu yüzden ilk iş, karşınızdaki ızgaranın 3×3 mü yoksa 4×4 mü olduğunu kesinleştirmektir — kod bunu rc-image-tile-33 / rc-image-tile-44 sınıf adından okur.
Adım 1: Izgara görüntüsünü yakalayın
Challenge iframe'ine geçin, talimat metnini ve ızgara görselini alın, ardından boyutu (3×3 mü 4×4 mü) sınıf adından belirleyin. Bu aşamada sayfadan üç şeyi çıkarırsınız:
- Ana sayfadaki reCAPTCHA çerçevesinin son iframe'i olan challenge iframe'i.
.rc-imageselect-desc-wrapperiçindeki talimat metni.img.rc-image-tile-33/img.rc-image-tile-44görselinin base64 ekran görüntüsü.
Python (Selenium)
import base64
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
driver.get("https://example.com/form")
# Wait for reCAPTCHA iframe
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, "iframe[src*='recaptcha']"))
)
# Switch to challenge iframe
iframes = driver.find_elements(By.CSS_SELECTOR, "iframe[src*='recaptcha']")
challenge_iframe = iframes[-1] # Challenge iframe is typically the last one
driver.switch_to.frame(challenge_iframe)
# Get the grid image
grid_img = driver.find_element(By.CSS_SELECTOR, "img.rc-image-tile-33, img.rc-image-tile-44")
img_src = grid_img.get_attribute("src")
# Get instruction text
instruction = driver.find_element(
By.CSS_SELECTOR, ".rc-imageselect-desc-wrapper"
).text
print(f"Instruction: {instruction}")
# Screenshot the grid as base64
img_b64 = grid_img.screenshot_as_base64
# Determine grid size
classes = grid_img.get_attribute("class")
grid_size = "4x4" if "44" in classes else "3x3"
print(f"Grid size: {grid_size}")
driver.switch_to.default_content()
JavaScript (Puppeteer)
const puppeteer = require('puppeteer');
const fs = require('fs');
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
await page.goto('https://example.com/form');
// Find the challenge iframe
const frames = page.frames();
const challengeFrame = frames.find(f => f.url().includes('recaptcha'));
// Get instruction
const instruction = await challengeFrame.$eval(
'.rc-imageselect-desc-wrapper',
el => el.textContent.trim()
);
// Screenshot the grid image
const gridImg = await challengeFrame.$('img.rc-image-tile-33, img.rc-image-tile-44');
const imgBuffer = await gridImg.screenshot();
const imgBase64 = imgBuffer.toString('base64');
// Determine grid size
const className = await challengeFrame.$eval(
'img.rc-image-tile-33, img.rc-image-tile-44',
el => el.className
);
const gridSize = className.includes('44') ? '4x4' : '3x3';
console.log(`Grid: ${gridSize}, Instruction: ${instruction}`);
Bu adımdan üç çıktı taşırsınız: img_b64 (çözücüye göndereceğiniz görsel), instruction (hangi nesnenin seçileceği) ve grid_size. Üçü de bir sonraki isteğin girdisidir; herhangi biri eksik ya da yanlışsa çözüm ya reddedilir ya da yanlış hücreler döner.
Adım 2: Görüntüyü CaptchaAI'ye gönderin
Base64 görselini in.php'ye gönderin, dönen görev kimliğini res.php üzerinden sorgulayın. Talimattaki anahtar kelimeyi (örneğin traffic lights) instructions alanına koyun.
instructions alanı çözücüye ne aradığını söyler; talimat cümlesinden yalnızca anahtar nesneyi ("traffic lights", "crosswalks", "buses") ayıklayıp gönderin. grid_size alanını da eklediğinizde yanıt, o boyuta uygun aralıkta indeks döndürür (3×3 için 1–9, 4×4 için 1–16).
Sonucu sorgulama
Sonuç hazır olana kadar res.php'yi birkaç saniyede bir sorgularsınız; CAPCHA_NOT_READY yanıtı "henüz hazır değil, beklemeye devam edin" demektir. Görev tamamlandığında status alanı 1 döner ve request içinde hücre indeksleri gelir.
import requests
import time
import json
API_KEY = "YOUR_API_KEY"
# Parse the instruction to a simple keyword
# "Select all images with traffic lights" → "traffic lights"
import re
keyword_match = re.search(r'(?:with|of|containing)\s+(.+?)\.?$', instruction, re.I)
keyword = keyword_match.group(1) if keyword_match else instruction
# Submit
with open("/tmp/grid.png", "wb") as f:
f.write(base64.b64decode(img_b64))
with open("/tmp/grid.png", "rb") as f:
resp = requests.post("https://ocr.captchaai.com/in.php",
files={"file": f},
data={
"key": API_KEY,
"method": "post",
"grid_size": grid_size,
"img_type": "recaptcha",
"instructions": keyword,
"json": "1",
}
).json()
if resp["status"] != 1:
raise Exception(f"Submit error: {resp['request']}")
task_id = resp["request"]
# Poll
for _ in range(20):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get", "id": task_id, "json": "1"
}).json()
if result["status"] == 1:
cells = json.loads(result["request"])
print(f"Cells to click: {cells}") # e.g., [1, 3, 6, 9]
break
if result["request"] != "CAPCHA_NOT_READY":
raise Exception(f"Error: {result['request']}")
Adım 3: Hücre indekslerini koordinatlara haritalayın
CaptchaAI'nin döndürdüğü 1 tabanlı indeksleri ızgara içindeki piksel merkezlerine çevirin: indeksi satır ve sütuna ayırın, hücre boyutuyla çarpın, ortaya hizalayın. Formülün mantığı üç parçadan oluşur:
- Satır/sütun: indeksten 1 çıkarın; sütun
idx % sütun_sayısı, satıridx // sütun_sayısıolur. - Hücre boyutu: ızgara genişliğini ve yüksekliğini sütun/satır sayısına bölün.
- Merkez: hücrenin sol üst köşesine yarım hücre ekleyerek ortayı bulun — tıklamanın kenara değil ortaya düşmesi isabeti artırır.
def cell_to_coordinates(cell_index, grid_size, grid_width, grid_height):
"""Convert a 1-based cell index to (x, y) center coordinates."""
if grid_size == "3x3":
cols, rows = 3, 3
else:
cols, rows = 4, 4
cell_w = grid_width / cols
cell_h = grid_height / rows
# Convert 1-based index to 0-based row/col
idx = cell_index - 1
col = idx % cols
row = idx // cols
# Center of the cell
x = col * cell_w + cell_w / 2
y = row * cell_h + cell_h / 2
return int(x), int(y)
# Example: grid is 300×300
for cell in cells:
x, y = cell_to_coordinates(cell, grid_size, 300, 300)
print(f"Cell {cell} → ({x}, {y})")
Not: ızgara boyutlarını her zaman tarayıcıdan canlı okuyun. reCAPTCHA piksel boyutlarını ekran çözünürlüğüne ve zoom seviyesine göre değiştirebilir; sabit 300×300 varsayımı yalnızca örnek amaçlıdır.
3×3 ızgara için örnek çıktı (300×300 piksel):
Cell 1 → (50, 50)
Cell 3 → (250, 50)
Cell 6 → (250, 150)
Cell 9 → (250, 250)
Adım 4: Hücrelere tıklayın ve doğrulayın
Koordinatları ızgara öğesinin sol üst köşesine göre uygulayın. Selenium'da move_to_element_with_offset ofseti öğenin merkezinden ölçer; bu yüzden hesapladığınız merkez koordinatından ızgaranın yarı genişliğini ve yarı yüksekliğini çıkarırsınız. Puppeteer tarafında ise tabloyu satır/sütun olarak gezip hücreyi doğrudan seçmek daha güvenilirdir — piksel aritmetiği hiç devreye girmez.
Selenium
from selenium.webdriver.common.action_chains import ActionChains
driver.switch_to.frame(challenge_iframe)
# Get grid element position and size
grid_el = driver.find_element(By.CSS_SELECTOR, ".rc-imageselect-target")
grid_rect = grid_el.rect
grid_w = grid_rect["width"]
grid_h = grid_rect["height"]
actions = ActionChains(driver)
for cell in cells:
x, y = cell_to_coordinates(cell, grid_size, grid_w, grid_h)
# Click relative to grid element's top-left corner
actions.move_to_element_with_offset(
grid_el,
x - grid_w / 2, # offset from center
y - grid_h / 2
).click()
actions.perform()
# Click verify
verify_btn = driver.find_element(By.ID, "recaptcha-verify-button")
verify_btn.click()
driver.switch_to.default_content()
Puppeteer
// Click each cell by index
const tableRows = await challengeFrame.$$('table.rc-imageselect-table tr');
for (const cellIdx of cells) {
const row = Math.floor((cellIdx - 1) / (gridSize === '4x4' ? 4 : 3));
const col = (cellIdx - 1) % (gridSize === '4x4' ? 4 : 3);
const cell = (await tableRows[row].$$('td'))[col];
await cell.click();
await new Promise(r => setTimeout(r, 200));
}
await challengeFrame.click('#recaptcha-verify-button');
Değişen (dinamik) döşemeleri yönetme
Bazı reCAPTCHA v2 ızgaraları tıkladığınız döşemeyi yenisiyle değiştirir. Tek geçiş yetmez; ızgarayı yeniden yakalayıp çözen kısa bir döngü kurun. Döngünün üç sorumluluğu vardır:
- Her turda ızgarayı ve talimatı yeniden yakalamak.
- Yeni indeksler için CaptchaAI'ye tekrar göndermek.
- Challenge iframe'i kaybolduğunda çözümün tamamlandığını anlamak.
İpucu: tur sayısını makul bir üst sınırla (
max_rounds) tutun. Sonsuz döngü, dinamik ızgara hiç bitmediğinde thread'inizi gereksiz meşgul eder.
Yeniden deneme döngüsü
def solve_with_dynamic_tiles(driver, api_key, max_rounds=3):
for round_num in range(max_rounds):
driver.switch_to.frame(challenge_iframe)
# Re-capture grid and instruction
img_b64 = driver.find_element(
By.CSS_SELECTOR, "img.rc-image-tile-33"
).screenshot_as_base64
# Submit and get cells (same as above)
cells = submit_and_poll(api_key, img_b64, "3x3", keyword)
if not cells:
break
# Click cells
click_cells(driver, cells, "3x3")
# Click verify
driver.find_element(By.ID, "recaptcha-verify-button").click()
driver.switch_to.default_content()
time.sleep(2)
# Check if solved (no more challenge iframe)
try:
driver.switch_to.frame(challenge_iframe)
driver.switch_to.default_content()
except Exception:
return True # Solved
return False
Türk pazarında tipik kullanım ve KVKK notu
Türkiye'deki e-ticaret ve fintech siteleri hesap açma ve sipariş akışlarını sıklıkla reCAPTCHA v2 ile korur; bu akışların uçtan uca QA testlerinde ızgara CAPTCHA en sık karşılaşılan engellerden biridir. Otomasyonu yalnızca yetkili olduğunuz kendi staging ortamlarınızda çalıştırın. Test verileri gerçek kişisel veri içeriyorsa bunların KVKK (Kişisel Verilerin Korunması Kanunu) kapsamına girdiğini unutmayın; mümkün olduğunca +90 telefon ve tr-TR biçiminde üretilmiş sahte veriyle çalışın.
Sorun giderme
| Sorun | Sebep | Düzeltme |
|---|---|---|
| Yanlış hücreler döndü | Yanlış grid_size |
Izgaranın 3×3 mü yoksa 4×4 mü olduğunu doğrulayın |
| Tıklamalar hücreleri ıskalıyor | Koordinat ofseti hatalı | Izgara öğesinin boyutlarını yeniden ölçün |
ERROR_WRONG_FILE_EXTENSION |
Hatalı görüntü formatı | PNG veya JPEG gönderin |
| Tıkladıktan sonra yeni döşemeler beliriyor | Dinamik ızgara | Her turdan sonra yeniden çözün |
Isabet oranını artırma
Tıklamalar sürekli ıskalıyorsa önce ızgara boyutunu doğrulayın, sonra öğe boyutlarını yeniden ölçün — sabit varsayım değil, canlı rect değerlerini kullanın. Görseli kırpmadan ve yeniden sıkıştırmadan gönderin; ekran görüntüsünü doğrudan base64'e çevirmek en temiz girdiyi verir.
Sık sorulan sorular
Izgara CAPTCHA çözümü ne kadar sürer?
Süre görüntü karmaşıklığına ve sunucu yüküne göre değişir; sonucu res.php üzerinden birkaç saniyede bir sorgulayın, CAPCHA_NOT_READY geldiği sürece bekleyin. Dinamik ızgaralarda süre tur sayısıyla artar.
CaptchaAI hCaptcha ızgaralarını da çözüyor mu?
Hayır. CaptchaAI reCAPTCHA v2 görüntü zorluklarını ve ızgara OCR görevlerini destekler; ancak hCaptcha ve FunCaptcha desteklenmez. Bu akış yalnızca reCAPTCHA v2 tarzı ızgaralar içindir.
Koordinatları piksel piksel tam vermem gerekir mi?
Hayır, hücre merkezine yakın olması yeterlidir. Kod her hücrenin ortasını hedefler; birkaç piksellik sapma sorun çıkarmaz. Asıl belirleyici nokta ızgara boyutunu (grid_size) doğru belirlemektir.
Fiyatlandırma çözüm başına mı hesaplanıyor?
Hayır. CaptchaAI eşzamanlı thread başına faturalandırır; her planda thread başına sınırsız çözüm vardır. BASIC ($15/ay, 5 thread) ile başlayıp hacim büyüdükçe üst planlara geçebilirsiniz. Fiyatlar USD'dir; bu da TL dalgalanmasından bağımsız, öngörülebilir bir maliyet sağlar.
Aynı anda birkaç ızgara CAPTCHA çözebilir miyim?
Eşzamanlı çözüm sayısı planınızın thread sayısına bağlıdır: BASIC ($15/ay, 5 thread) ile aynı anda beş görevi işleyebilirsiniz. Her thread bağımsız çalışır; daha yüksek hacimli QA akışları için üst planlara geçerek eşzamanlılığı artırırsınız.
Izgara CAPTCHA'larını CaptchaAI ile çözmeye başlayın
API anahtarınızı captchaai.com üzerinden alın, örnek kodu iş akışınıza yapıştırın ve ilk ızgara CAPTCHA'nızın hücre indekslerini alın. Planlar thread tabanlı ve USD fiyatlıdır; günlük çözüm sınırı yoktur.