Cara scraping hasil pencarian melewati captcha (panduan Python, 2026)
Halaman hasil pencarian adalah salah satu tempat pertama scraper bertemu captcha. Situs melihat lonjakan request dari satu alamat, menyajikan tantangan, dan tidak mengembalikan hasil sampai tantangan itu dilewati. Untuk scraping hasil pencarian melewati captcha, skrip Anda membutuhkan tiga langkah: deteksi tantangan sebelum mem-parse, pecahkan dengan satu panggilan API, lalu kirim token agar situs mengembalikan halaman hasil yang sebenarnya.
Panduan ini menunjukkan alur tersebut dengan Python menggunakan requests dan BeautifulSoup. Panduan ini mencakup halaman yang menampilkan widget PopularCaptcha, yaitu jenis yang dipecahkan Scarnox saat ini (proxyless). Mulai dengan kredit uji coba gratis, tanpa kartu dan jalankan kode terhadap halaman milik Anda sendiri terlebih dahulu.
Seperti apa tantangannya
Halaman pencarian biasanya meletakkan widget di dalam form. Kontainer widget membawa atribut data-sitekey, dan form mengirim balik ke situs:
<form action="/search/verify" method="post">
<input type="hidden" name="q" value="web scraping">
<input type="hidden" name="lang" value="en">
<div class="h-captcha" data-sitekey="YOUR-SITEKEY-UUID"></div>
<button type="submit">Continue</button>
</form>
Kode Anda membutuhkan tiga hal dari markup ini: sitekey, URL action form, dan field tersembunyi yang harus dikirim kembali bersama token. Helper di bawah membaca ketiganya, jadi tidak perlu menulis nilainya secara permanen di kode.
Jika widget pada target Anda adalah jenis captcha yang berbeda, lihat jenis captcha. Dukungan reCAPTCHA dan Cloudflare Turnstile segera hadir, jadi kode di sini hanya mencakup PopularCaptcha.
Panggilan solver
Request solve dikirim ke API Scarnox dengan kunci Anda di header Bearer. Panggilan ini menunggu sampai token siap, jadi tidak ada loop polling:
import time
from urllib.parse import urljoin
import requests
from bs4 import BeautifulSoup
API_KEY = "scarnox_YOURAPIKEY"
SEARCH_URL = "https://search.example.com/search"
session = requests.Session()
session.headers["User-Agent"] = (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0 Safari/537.36"
)
def solve(sitekey: str, page_url: str) -> str:
r = requests.post(
"https://api.scarnox.com/api/tasks/create",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"captcha_type": "PopularCaptchaTaskProxyless",
"site_key": sitekey,
"site_url": page_url,
},
timeout=185, # panggilan kembali ketika token sudah siap
)
data = r.json()
if data.get("errorId") != 0:
raise RuntimeError(f"{data.get('errorCode')}: {data.get('errorDescription')}")
return data["solution"]["token"]
Solve yang gagal mengembalikan errorId selain 0, dan Anda tidak dikenakan biaya untuk itu. Retry dibahas di penanganan error solver captcha.
Ambil halaman dan lewati captcha
Fungsi fetch memeriksa widget terlebih dahulu. Jika tidak ada, ia mengembalikan HTML apa adanya. Jika ada, ia memecahkan tantangan, menyusun ulang form dengan field tersembunyi yang sama, lalu mengirimkannya:
def fetch_results(query: str, page: int = 1) -> str:
resp = session.get(SEARCH_URL, params={"q": query, "page": page}, timeout=30)
soup = BeautifulSoup(resp.text, "html.parser")
widget = soup.select_one("[data-sitekey]")
if widget is None:
return resp.text # tidak ada tantangan di halaman ini
form = widget.find_parent("form")
if form is None:
raise RuntimeError("Widget captcha tidak berada di dalam form")
token = solve(widget["data-sitekey"], resp.url)
payload = {
field["name"]: field.get("value", "")
for field in form.select("input[name]")
}
payload["h-captcha-response"] = token
payload["g-recaptcha-response"] = token
action = urljoin(resp.url, form.get("action") or resp.url)
verified = session.post(action, data=payload, timeout=30)
if "data-sitekey" in verified.text:
raise RuntimeError("Tantangan masih ditampilkan setelah pengiriman; token mungkin ditolak")
return verified.text
Ada dua detail yang penting di sini. site_url adalah URL tempat captcha benar-benar disajikan (resp.url, yang mencakup pengalihan apa pun), bukan endpoint pencarian polos. Dan sesi menyimpan cookie di antara GET dan POST, yang banyak situs butuhkan untuk menerima token.
Token kedaluwarsa dalam sekitar dua menit, itulah sebabnya solve dilakukan tepat setelah form dibaca, bukan sebelumnya. Untuk penjelasan lebih lanjut tentang jendela waktu ini, lihat masa berlaku token captcha.
Parse hasilnya
Setelah halaman hasil yang sebenarnya dikembalikan, parsing adalah pekerjaan HTML biasa. Selector di bawah hanyalah placeholder; buka halaman di DevTools dan ganti dengan selector yang sebenarnya:
def parse_results(html: str) -> list[dict]:
soup = BeautifulSoup(html, "html.parser")
rows = []
for item in soup.select("div.result"):
link = item.select_one("a[href]")
heading = item.select_one("h3")
if link and heading:
rows.append({
"title": heading.get_text(strip=True),
"url": link["href"],
})
return rows
if __name__ == "__main__":
for page in range(1, 4):
html = fetch_results("web scraping", page)
for row in parse_results(html):
print(row)
time.sleep(5) # atur jeda antar halaman
Simpan output setiap halaman secara terpisah. Jika sebuah halaman mengembalikan nol baris, periksa keberadaan widget sebelum menyimpulkan bahwa kueri tersebut memang tidak punya hasil.
Scraping secara bertanggung jawab
Captcha adalah sinyal, bukan celah. Sebelum Anda menjalankan ini terhadap situs pencarian mana pun:
- Baca robots.txt dan ketentuan layanan. Banyak situs pencarian melarang kueri otomatis. Jika ketentuannya melarangnya, jangan jalankan skrip.
- Batasi laju.
time.sleep(5)di atas adalah batas bawah, bukan target. Perlambat lebih jauh jika Anda melihat lebih banyak tantangan. - Batasi apa yang Anda simpan. Hasil pencarian bisa berisi nama, email, dan data pribadi lainnya. Simpan hanya field yang Anda butuhkan, dan hapus sisanya.
- Utamakan API resmi jika situs menyediakannya. Itu lebih andal dan biasanya lebih murah daripada scraping HTML.
Untuk sisi hukumnya, lihat apakah web scraping legal. Untuk menghindari pemblokiran sejak awal, lihat scrape tanpa terblokir.
Harga
Scarnox menagih per solve yang berhasil, dan solve yang gagal gratis. Lihat harga terkini untuk tarifnya. Mulai dengan kredit uji coba gratis, tanpa kartu.