Slider yang harus digeser tepat sasaran, gambar yang harus diputar tegak, ikon yang mesti diklik berurutan, sampai tantangan audio — semua CAPTCHA kustom itu bisa Anda tangani lewat satu jalur yang sama di CaptchaAI: ambil screenshot elemennya, encode ke base64, lalu kirim bersama instruksi teks ke endpoint in.php. Anda tidak perlu solver berbeda untuk tiap widget aneh. Artikel ini menunjukkan pola universal itu dengan Python — dari mengenali jenis tantangan di halaman, mengirim gambar plus instruksi, sampai memetakan jawaban kembali ke aksi Selenium untuk slider, rotasi, urutan klik, dan audio.
Kapan pendekatan gambar + instruksi teks masuk akal
Sebagian tipe sudah punya method khusus di API dan sebaiknya Anda tangani lewat panduannya sendiri, bukan pola di artikel ini:
- reCAPTCHA v2/v3 → method
userrecaptcha - Cloudflare Turnstile → method
turnstile - GeeTest v3 → method
geetest
Pola gambar + instruksi teks di sini justru untuk tantangan yang tidak punya method khusus:
- Widget JavaScript buatan situs
- Slider bergaya jigsaw
- Rotasi orientasi gambar
- Soal aritmatika yang dirender sebagai gambar
Kuncinya sederhana. Selama tantangan bisa Anda tangkap sebagai gambar dan jelaskan dengan kalimat, Anda bisa mengirimnya ke jalur OCR (method=base64) dengan parameter textinstructions. Ini realistis untuk pekerjaan lapangan: tim price-monitoring dan freelancer scraping di Jakarta atau Bandung kerap menemui slider atau rotasi di form pendaftaran ketika membangun QA otomatis pada lingkungan staging.example.com milik sendiri — dan pola inilah yang menanganinya tanpa harus menulis pemecah khusus per situs.
Kenali jenis CAPTCHA kustom di halaman
Sebelum menulis kode, petakan dulu tantangan yang Anda hadapi ke pendekatan yang tepat. Tabel ini merangkum tipe kustom yang paling sering muncul:
| Tipe | Karakteristik | Pendekatan |
|---|---|---|
| Slider CAPTCHA | Geser ke posisi | Screenshot sebagai gambar, pakai instruksi teks |
| Puzzle (jigsaw) | Geser potongan agar pas | Dapat dipetakan ke solve bergaya GeeTest v3 |
| Audio CAPTCHA | Dengarkan dan ketik | Kirim file audio |
| Rotasi gambar | Putar ke orientasi benar | Screenshot + instruksi |
| Pilih berurutan | Klik item satu per satu | Pakai pendekatan grid gambar |
| Persamaan matematika | Selesaikan aritmatika | Pakai parameter calc=1 |
| Widget interaktif kustom | Widget JS khusus situs | Screenshot + instruksi teks |
Pola universal: kirim gambar base64 plus instruksi
Fungsi berikut adalah inti dari semua contoh sesudahnya. Alurnya mengikuti frame empat langkah yang sama seperti solve CAPTCHA lain di CaptchaAI:
- Kirim task berisi gambar base64 dan instruksi ke
in.php - Simpan task ID dari respons
- Polling
res.phpsampai status siap - Pakai jawaban yang dikembalikan
Bedanya, di sini Anda menyertakan textinstructions yang memberi tahu solver apa persisnya yang harus dikembalikan — angka, koordinat, teks, atau daftar urutan.
import requests
import base64
import time
import os
API_KEY = os.environ["CAPTCHAAI_API_KEY"]
def solve_custom_captcha(image_b64, instructions):
"""Solve any visual CAPTCHA using image + text instructions."""
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "base64",
"body": image_b64,
"textinstructions": instructions,
"json": 1,
}, timeout=30)
result = resp.json()
if result.get("status") != 1:
raise RuntimeError(result.get("request"))
task_id = result["request"]
time.sleep(10)
for _ in range(30):
resp = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get",
"id": task_id, "json": 1,
}, timeout=15)
data = resp.json()
if data.get("status") == 1:
return data["request"]
if data["request"] != "CAPCHA_NOT_READY":
raise RuntimeError(data["request"])
time.sleep(5)
raise TimeoutError("Solve timeout")
Semakin spesifik instruksi Anda, semakin bersih jawaban yang kembali. Minta "hanya angka X offset", bukan "jelaskan slider ini".
Slider: ubah jawaban jadi offset drag
Slider meminta Anda menggeser handle ke titik tertentu. Screenshot area CAPTCHA, tanyakan posisi piksel targetnya, lalu terjemahkan angka itu menjadi gerakan drag dengan ActionChains:
# slider_captcha.py
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
def solve_slider_captcha(driver, captcha_selector):
"""Screenshot slider CAPTCHA and solve via CaptchaAI."""
captcha = driver.find_element(By.CSS_SELECTOR, captcha_selector)
image_b64 = captcha.screenshot_as_base64
result = solve_custom_captcha(
image_b64,
"What pixel position should the slider be dragged to? "
"Return only the X offset number."
)
try:
offset = int(result)
except ValueError:
return False
# Drag slider to position
slider = driver.find_element(By.CSS_SELECTOR, ".slider-handle")
ActionChains(driver).click_and_hold(slider).move_by_offset(offset, 0).release().perform()
return True
Rotasi: hitung derajat lalu klik
Untuk CAPTCHA rotasi, gambar harus diputar tegak. Alurnya dua langkah:
- Minta solver mengembalikan jumlah derajat searah jarum jam
- Bagi dengan 90 untuk menentukan berapa kali tombol putar diklik
# rotation_captcha.py
def solve_rotation_captcha(driver, captcha_selector):
"""Solve rotation CAPTCHA."""
captcha = driver.find_element(By.CSS_SELECTOR, captcha_selector)
image_b64 = captcha.screenshot_as_base64
result = solve_custom_captcha(
image_b64,
"How many degrees should this image be rotated clockwise "
"to be in the correct upright orientation? Return only the number."
)
try:
degrees = int(result)
except ValueError:
return False
# Click rotation button the correct number of times
rotate_btn = driver.find_element(By.CSS_SELECTOR, ".rotate-button")
clicks = degrees // 90 # Each click rotates 90 degrees
for _ in range(clicks):
rotate_btn.click()
time.sleep(0.3)
return True
Urutan klik: petakan angka ke elemen
Beberapa CAPTCHA meminta Anda mengklik item dalam urutan tertentu — misalnya angka atau ikon dari kecil ke besar. Minta jawaban sebagai daftar angka posisi (1-indexed) dipisah koma, lalu klik elemen sesuai urutan itu:
# order_captcha.py
def solve_order_captcha(driver, captcha_selector, item_selector):
"""Solve click-in-order CAPTCHA."""
captcha = driver.find_element(By.CSS_SELECTOR, captcha_selector)
image_b64 = captcha.screenshot_as_base64
result = solve_custom_captcha(
image_b64,
"What is the correct order? Return as comma-separated "
"numbers (1-indexed) representing positions left-to-right, top-to-bottom."
)
# Parse order
try:
order = [int(x.strip()) for x in result.split(",")]
except ValueError:
return False
# Click items in order
items = driver.find_elements(By.CSS_SELECTOR, item_selector)
for idx in order:
if 1 <= idx <= len(items):
items[idx - 1].click()
time.sleep(0.5)
return True
Alternatif audio
Banyak situs menyediakan opsi audio sebagai alternatif aksesibilitas. Unduh file audionya, encode ke base64, lalu kirim lewat fungsi yang sama dengan instruksi transkripsi:
# audio_captcha.py
import requests
def solve_audio_captcha(audio_url):
"""Download and solve an audio CAPTCHA."""
# Download audio
resp = requests.get(audio_url, timeout=30)
audio_b64 = base64.b64encode(resp.content).decode("ascii")
# Submit as image with instructions
# CaptchaAI may support audio via the base64 method
result = solve_custom_captcha(
audio_b64,
"This is an audio CAPTCHA. Transcribe the spoken characters."
)
return result
Widget CAPTCHA kustom sepenuhnya buatan situs
Kalau tantangannya widget unik yang tidak cocok kategori mana pun, perlakukan seperti kotak hitam. Kode di bawah menjalankan empat langkah:
- Screenshot seluruh widget
- Tarik teks instruksi yang terlihat di halaman
- Kirim gambar dan instruksi ke solver
- Masukkan jawaban ke input yang tersedia
Pendekatan ini bertahan meski markup situs berubah:
# custom_widget.py
from selenium import webdriver
from selenium.webdriver.common.by import By
def handle_custom_widget(driver, widget_selector):
"""Handle an unknown custom CAPTCHA widget."""
# Step 1: Screenshot the entire widget
widget = driver.find_element(By.CSS_SELECTOR, widget_selector)
image_b64 = widget.screenshot_as_base64
# Step 2: Get any visible instructions
try:
instructions_el = widget.find_element(By.CSS_SELECTOR, ".instructions, .prompt, p")
visible_instructions = instructions_el.text
except Exception:
visible_instructions = "Solve this CAPTCHA"
# Step 3: Submit with descriptive instructions
result = solve_custom_captcha(
image_b64,
f"CAPTCHA instructions: {visible_instructions}. "
f"Return the answer text."
)
# Step 4: Try to submit result
try:
input_el = widget.find_element(By.CSS_SELECTOR, "input")
input_el.clear()
input_el.send_keys(result)
except Exception:
# No input — try clicking based on result
driver.execute_script("""
var input = document.querySelector('input[name*="captcha"]');
if (input) input.value = arguments[0];
""", result)
return result
Deteksi jenis CAPTCHA secara otomatis
Kalau halaman yang Anda proses bisa memuat tantangan yang berbeda-beda, deteksi tipenya lebih dulu lalu arahkan ke handler yang sesuai. Fungsi ini memindai HTML halaman dengan pola regex sederhana dan mengembalikan daftar tipe yang terdeteksi:
# detector.py
import re
def detect_captcha_type(page_html):
"""Detect which CAPTCHA type is on a page."""
checks = {
"recaptcha_v2": r'data-sitekey.*g-recaptcha',
"recaptcha_v3": r'recaptcha/api\.js\?render=',
"turnstile": r'cf-turnstile|challenges\.cloudflare\.com/turnstile',
"geetest": r'gt\b.*challenge|geetest',
"bls": r'method.*bls|bls-captcha',
"image_text": r'captcha.*\.(png|jpg|gif|jpeg)',
"slider": r'slider.*captcha|slide.*verify',
"audio": r'audio.*captcha|captcha.*audio',
}
detected = []
for captcha_type, pattern in checks.items():
if re.search(pattern, page_html, re.IGNORECASE):
detected.append(captcha_type)
return detected if detected else ["unknown"]
Simpan hasil deteksi ini sebagai router sederhana:
recaptcha_v2/recaptcha_v3/turnstile→ arahkan ke method khususnyaslider/audio/ tipe kustom lain → jatuhkan ke pola gambar + instruksiunknown→ gunakanhandle_custom_widgetsebagai jalur cadangan
Troubleshooting
Sebagian besar kegagalan pada CAPTCHA kustom bersumber dari kualitas screenshot atau instruksi yang ambigu. Tabel ini merangkum masalah yang paling umum:
| Masalah | Penyebab | Perbaikan |
|---|---|---|
ERROR_CAPTCHA_UNSOLVABLE |
Gambar tidak jelas atau instruksi ambigu | Tingkatkan kualitas screenshot dan perjelas instruksi |
| Format jawaban salah | Solver mengembalikan deskripsi, bukan nilai | Lebih spesifik: "Kembalikan hanya angkanya" |
| Widget kustom tidak ter-capture | Elemen di luar viewport | Scroll ke elemen sebelum screenshot |
| Interaksi gagal | Koordinat klik salah | Petakan solusi ke elemen UI sebenarnya dengan teliti |
Biaya menyelesaikan CAPTCHA kustom dalam volume tinggi
Karena CAPTCHA kustom biasanya muncul di alur bervolume tinggi seperti QA otomatis atau pemantauan harga, biaya jadi pertimbangan nyata — terutama untuk tim dan freelancer yang sensitif terhadap ongkos. CaptchaAI menagih per thread bersamaan, bukan per solve: satu thread menangani satu CAPTCHA in-flight, dan begitu selesai, thread itu langsung bebas untuk tugas berikutnya. Paket dimulai dari BASIC ($15/bulan, 5 thread) dan naik lewat STANDARD ($30/bulan, 15 thread), ADVANCE ($90/bulan, 50 thread), hingga tier tinggi seperti VIP-3 ($7,500/bulan, 5.000 thread) — dan setiap paket memberi solve tak terbatas per thread selama sebulan. Untuk OCR gambar standar, waktu solve biasanya di bawah 0.5 detik per solve, sehingga throughput ditentukan oleh jumlah thread, bukan tagihan per tantangan. Catatan kepatuhan: sesuai UU Pelindungan Data Pribadi (UU 27/2022), proses hanya data yang berhak Anda akses dan hindari data pribadi.
Pertanyaan Umum
Bisakah satu pola screenshot dipakai untuk slider dan puzzle sekaligus?
Bisa. Selama tantangan dapat ditangkap sebagai gambar dan dijelaskan dengan instruksi teks, fungsi solve_custom_captcha yang sama menanganinya — Anda hanya mengganti kalimat instruksinya (posisi offset untuk slider, potongan yang pas untuk puzzle).
Berapa lama waktu penyelesaian untuk gambar + instruksi teks?
Untuk OCR gambar standar, penyelesaian umumnya di bawah 0.5 detik per solve. Tantangan kustom dengan instruksi kompleks bisa memerlukan beberapa detik lebih dan Anda ambil hasilnya lewat polling res.php, bukan seketika.
Bisakah puzzle geser bergaya GeeTest diselesaikan?
GeeTest v3 didukung secara native lewat method geetest, jadi puzzle bergaya GeeTest bisa ditangani langsung. GeeTest v4 belum tersedia — statusnya masih segera hadir. Untuk puzzle geser non-GeeTest, gunakan pola gambar + instruksi di artikel ini.
Berapa banyak thread yang saya butuhkan untuk scraping paralel?
Tergantung berapa CAPTCHA yang berjalan bersamaan. Satu thread menangani satu solve in-flight; kalau Anda memproses 40 halaman paralel, ADVANCE ($90/bulan, 50 thread) memberi ruang yang cukup dengan solve tak terbatas per thread.
Panduan Terkait
Selesaikan CAPTCHA kustom apa pun — mulai dengan CaptchaAI.