Cara Memecahkan CAPTCHA di Jupyter Tanpa Error asyncio.run

Untuk memecahkan CAPTCHA di notebook Jupyter, instal paket capskip dengan %pip agar paket itu masuk ke Python milik kernel itu sendiri. Lalu panggil CapSkip dari sebuah sel seperti yang Anda lakukan di skrip, atau lakukan await pada klien AsyncCapSkip-nya langsung di level teratas sel. Yang tidak boleh Anda lakukan adalah membungkus pemanggilan async itu dengan asyncio.run(). Kernel sudah menjalankan event loop, sehingga asyncio.run memunculkan RuntimeError, dan API sinkron milik Playwright menolak untuk berjalan karena alasan yang sama. Pemecahan CAPTCHA di notebook Jupyter juga punya dua jebakan tersendiri: tombol stop tidak selalu bisa menghentikan pemecahan, dan di Windows ipykernel versi lama mencegah Playwright meluncurkan browser. Panduan ini membahas instalasi, kedua klien, browser, dan kernel jarak jauh, dan sudah diuji pada ipykernel 7.4 dan 7.3.
Apa yang Anda butuhkan
- CapSkip yang berjalan di komputer Windows. Contoh kodenya memecahkan reCAPTCHA v2, dan setiap tipe lain yang ditangani SDK bekerja dengan cara yang sama di dalam sel.
- Python 3.10 atau lebih baru dan paket capskip versi terbaru (1.3.0 saat artikel ini ditulis), ditambah requests dan Beautiful Soup untuk halaman. Playwright hanya jika Anda membutuhkan browser.
- Jupyter dalam bentuk apa pun: Notebook 7, JupyterLab, atau editor notebook di VS Code. Ketiganya menjalankan sel Anda di ipykernel, yang menjadi sumber semua perilaku yang dibahas di bawah.
- Sebuah alamat untuk pemecah CAPTCHA. Mode Local menjawab di 127.0.0.1 hanya untuk perangkat itu; mode Server mendengarkan di alamat jaringan atau IP publik Anda sehingga kernel di mesin lain dapat memanggilnya melalui API. Keduanya ada di pengaturan koneksi, dan bagian terakhir membahas kapan Anda membutuhkan mode Server.
Langkah 1: instal ke Python milik kernel dengan %pip
Jalankan instalasi dari sel notebook, dengan tanda persen:
# pip install capskip requests beautifulsoup4, run inside the notebook: %pip install capskip requests beautifulsoup4
Tanda persen itu penting. Perintah magic %pip dari IPython menjalankan pip dengan interpreter milik kernel itu sendiri, sys.executable, sehingga paket masuk ke tempat sel Anda melakukan import. Tanda seru justru menyerahkan baris itu ke shell, yang lalu menjalankan pip mana pun yang muncul pertama di PATH. Di mesin dengan lebih dari satu Python, keduanya adalah instalasi yang berbeda. Dalam satu pengujian, %pip di kernel melaporkan capskip 1.3.0, sedangkan pip milik shell, dari Python 3.14 global, melaporkan versi lama 1.0.1 yang belum memiliki tipe CAPTCHA yang lebih baru. Periksa Python mana dan versi mana yang Anda dapatkan sebelum melanjutkan:
import sys import capskip print(sys.executable) # the Python this kernel runs on print(capskip.__version__) # 1.3.0 or later
Jika sebuah paket sudah di-import saat Anda meng-upgrade-nya, mulai ulang kernel agar versi barunya dimuat. IPython menampilkan pengingat yang sama setelah %pip.
Langkah 2: pecahkan di dalam sel dengan klien sinkron
Klien sinkron tidak membutuhkan perlakuan khusus di notebook. Ambil halaman dengan requests.Session, temukan widget-nya, lalu pecahkan:
import requests
from bs4 import BeautifulSoup
from capskip import CapSkip
PAGE_URL = "https://example.com/login"
# pollingInterval caps the wait between polls. At 1 instead of the
# default 5, the stop button takes effect within about a second.
solver = CapSkip(host="127.0.0.1", port=8080, pollingInterval=1)
session = requests.Session()
page = session.get(PAGE_URL, timeout=30)
soup = BeautifulSoup(page.text, "html.parser")
widget = soup.select_one(".g-recaptcha[data-sitekey]")
form = widget.find_parent("form")
token = solver.recaptcha(sitekey=widget["data-sitekey"], url=PAGE_URL)["code"]
len(token)Lalu kirim token itu di sel berikutnya, bersama field milik form itu sendiri dan sesi yang sama:
from urllib.parse import urljoin
def form_fields(form):
"""The fields a browser would send: hidden, text and checked boxes."""
fields = {}
for tag in form.select("input[name]"):
kind = (tag.get("type") or "text").lower()
if kind in ("submit", "button", "image", "file", "reset"):
continue
if kind in ("checkbox", "radio") and not tag.has_attr("checked"):
continue
fields[tag["name"]] = tag.get("value", "on" if kind in ("checkbox", "radio") else "")
return fields
data = form_fields(form)
data["username"] = "YOUR_USERNAME"
data["g-recaptcha-response"] = token
res = session.post(urljoin(PAGE_URL, form.get("action") or PAGE_URL), data=data,
headers={"Referer": PAGE_URL}, timeout=30)
res.status_codeSesi itu membawa cookie halaman ke kiriman form, dan itulah yang mengikat field CSRF tersembunyi ke kunjungan Anda. Header Referer menggantikan header yang biasanya dikirim browser: requests tidak mengirimnya sama sekali, dan sebagian framework, termasuk Django, menolak form post HTTPS tanpa Referer atau Origin. Token reCAPTCHA hanya berlaku untuk satu pengiriman dan sekitar dua menit, jadi jalankan sel pengiriman tepat setelah sel pemecahan, jangan kembali ke sel itu belakangan.
Tombol stop adalah hal yang membedakan notebook dari skrip. Interupsi memunculkan KeyboardInterrupt di sel Anda, tetapi pada kernel Windows interupsi itu baru masuk ketika pemanggilan yang sedang berjalan selesai. SDK menghabiskan sebagian besar waktu pemecahan dengan sleep di antara polling, sehingga sel berhenti ketika sleep itu berakhir: hingga lima detik dengan pollingInterval default, dan sekitar satu detik dengan pengaturan di atas. Traceback-nya tampak aneh, dengan NetworkException lebih dulu lalu KeyboardInterrupt yang dimunculkan saat menanganinya. NetworkException itu hanyalah sinyal belum siap dari SDK.
Kasus yang buruk adalah CapSkip yang menerima koneksi tetapi tidak pernah menjawab. Klien sinkron tidak menyetel timeout pada pemanggilan HTTP-nya, sehingga di Windows sel tertahan pada pembacaan socket yang tidak terjangkau interupsi apa pun, dan recaptchaTimeout tidak membantu karena SDK hanya memeriksanya di antara polling. Memulai ulang kernel akan membebaskannya tetapi menghilangkan semua variabel. Menutup CapSkip juga membebaskannya dan tetap mempertahankan variabel itu, karena koneksi yang terputus mengakhiri pembacaan dan interupsi yang sudah Anda kirim langsung masuk. Interupsi juga hanya menghentikan sel Anda, tidak pernah menghentikan CapSkip: SDK tidak punya pemanggilan untuk membatalkan job, sehingga pemecahan yang ditinggalkan tetap berjalan dan token-nya tidak pernah dibaca.
Langkah 3: async di dalam sel: await di level teratas, jangan pernah asyncio.run
Cara biasa menjalankan kode async dari skrip akan gagal di notebook:
import asyncio from capskip import AsyncCapSkip asolver = AsyncCapSkip(host="127.0.0.1", port=8080, pollingInterval=1) asyncio.run(asolver.recaptcha(sitekey=widget["data-sitekey"], url=PAGE_URL)) # RuntimeError: asyncio.run() cannot be called from a running event loop
ipykernel menjalankan setiap sel di dalam event loop yang sudah dimulainya, sedangkan asyncio.run bersikeras memulai event loop baru. Idiom yang lebih lama, asyncio.get_event_loop().run_until_complete(), juga gagal, dengan RuntimeError: This event loop is already running. Kedua pemanggilan itu tidak pernah sampai ke CapSkip, jadi tidak ada job yang dikirim. Coroutine yang Anda berikan tidak pernah berjalan, sehingga sel yang dijalankan kemudian mungkin menampilkan RuntimeWarning bahwa coroutine itu tidak pernah di-await; peringatan itu tidak berbahaya. Solusinya lebih sederhana daripada masalahnya. IPython memungkinkan Anda melakukan await di level teratas sel, di luar fungsi apa pun:
# No asyncio.run: the kernel's loop runs this await. from capskip import AsyncCapSkip asolver = AsyncCapSkip(host="127.0.0.1", port=8080, pollingInterval=1) result = await asolver.recaptcha(sitekey=widget["data-sitekey"], url=PAGE_URL) token = result["code"]
Karena itu AsyncCapSkip adalah klien yang lebih baik untuk notebook, dengan dua alasan di luar soal gaya. Interupsi langsung membatalkan await, sehingga sel segera berakhir, bukan setelah polling berikutnya. Selain itu, pemanggilan HTTP-nya melewati httpx, yang menyerah pada koneksi yang diam setelah lima detik secara default. Jika CapSkip berhenti menjawab, pemanggilan berakhir dengan error SDK, bukan macet: TimeoutException tidak lama setelah recaptchaTimeout terlewati jika polling tersendat, atau NetworkException setelah lima detik jika pengiriman job yang tersendat. Tombol stop tetap berfungsi sepanjang waktu. Setel recaptchaTimeout di constructor untuk mempersingkat waktu tunggu itu; recaptcha() tidak menerima argumen timeout di SDK Python, dan memberikannya akan memunculkan TypeError.
Beberapa pemecahan sekaligus cukup dengan satu gather. CapSkip memecahkan reCAPTCHA dengan 10 thread secara default, yaitu Max. Threads di pengaturannya, dan tugas yang mengantre di belakangnya menunggu hingga 250 detik sebelum CapSkip menggagalkannya, jadi batasi ukuran batch:
import asyncio
# Max. Threads for reCAPTCHA is 10 by default; more than that queues.
limit = asyncio.Semaphore(10)
async def solve(sitekey, url):
async with limit:
return (await asolver.recaptcha(sitekey=sitekey, url=url))["code"]
# jobs: (sitekey, url) pairs; here the Step 2 page three times
jobs = [(widget["data-sitekey"], PAGE_URL)] * 3
tokens = await asyncio.gather(*(solve(k, u) for k, u in jobs), return_exceptions=True)Fungsi gather mengembalikan semua token sekaligus di akhir, jadi segera kirim semuanya atau beralihlah ke asyncio.as_completed dan kirim setiap token begitu tiba. Dengan return_exceptions=True, pemecahan yang gagal kembali sebagai exception-nya di dalam daftar, bukan memunculkan error keluar dari sel, jadi kirim hanya entri yang berupa string. Pemecahan dalam satu batch berbagi satu mesin CapSkip, jadi perkirakan setiap pemecahan berjalan lebih lambat daripada pemecahan tunggal. Klien juga membuat klien HTTP baru untuk setiap polling, yang memakan sekitar sepersepuluh detik CPU kernel per polling di Windows, sehingga batch besar membuat satu core terus sibuk. Pola untuk batch yang lebih besar ada di panduan memecahkan CAPTCHA secara paralel di Python.
Jawaban lama untuk error asyncio.run merekomendasikan nest_asyncio. Lewati saja. Proyek itu diarsipkan pada Maret 2024. Di Python 3.14, menerapkannya merusak kernel: mulai sel berikutnya, setiap pemanggilan httpx gagal dengan TypeError tentang weak reference ke objek NoneType, termasuk AsyncCapSkip, sampai Anda memulai ulang kernel. Top-level await sama sekali tidak membutuhkan patch.
Langkah 4: browser di dalam notebook
Selenium tidak punya event loop sendiri, jadi sesi webdriver bekerja di dalam sel persis seperti di skrip: pecahkan dengan klien sinkron dari Langkah 2 lalu tulis token ke halaman. API sinkron milik Playwright memeriksa apakah ada loop yang sedang berjalan dan menolak dengan Error: It looks like you are using Playwright Sync API inside the asyncio loop. Please use the Async API instead. Jadi di notebook, Anda mengendalikan Playwright melalui API async-nya, dengan await di level teratas:
# pip install playwright into the kernel, then download a browser once:
%pip install playwright
import sys
!"{sys.executable}" -m playwright install chromiumfrom playwright.async_api import async_playwright
# start() instead of "async with", so the browser outlives this cell.
pw = await async_playwright().start()
browser = await pw.chromium.launch()
page = await browser.new_page()
await page.goto(PAGE_URL)
sitekey = await page.locator(".g-recaptcha").get_attribute("data-sitekey")
token = (await asolver.recaptcha(sitekey=sitekey, url=page.url))["code"]
# The widget's hidden textarea is the field the form submits.
await page.locator("#g-recaptcha-response").evaluate("(el, t) => { el.value = t; }", token)
await page.locator("form button[type=submit]").click()Menyimpan pw dan browser di variabel memungkinkan Anda mengutak-atik halaman dari sel berikutnya, dan itulah inti utama memakai notebook. Setelah selesai, tutup keduanya dengan await browser.close() dan await pw.stop(). Memanggil sys.executable milik kernel itu sendiri menyelaraskan browser dengan Playwright yang di-import sel Anda, dengan alasan yang sama seperti %pip. Tanda kutip menjaga path yang mengandung spasi tetap utuh, dan baris dengan tanda seru menampilkan progres unduhan di dalam sel. Penjelasan lebih lanjut tentang cara mengendalikan browser itu sendiri ada di panduan pemecah CAPTCHA Playwright.
Di Windows, periksa versi ipykernel Anda sebelum men-debug Playwright. Hingga versi 7.3, ipykernel di sana menjalankan sel pada selector event loop, yang tidak bisa memulai subprocess asyncio, sehingga chromium.launch() gagal dengan NotImplementedError tanpa keterangan apa pun. Versi 7.4.0, yang dirilis pada akhir September 2026, memindahkan sel Windows ke loop Proactor, dan sel yang sama pun berfungsi. Cetak ipykernel.__version__ untuk melihat versi yang Anda miliki. Untuk meng-upgrade, jalankan %pip install -U ipykernel di notebook lalu mulai ulang kernel. Jika Anda tidak bisa meng-upgrade, worker thread tidak membantu, karena policy selector berlaku untuk seluruh proses kernel. Sebagai gantinya, kendalikan browser dengan Selenium, yang memulai chromedriver tanpa asyncio.
Ketika kernel tidak berada di PC Anda: mode Server
Semua hal di atas mengasumsikan kernel berjalan di mesin yang sama dengan CapSkip, sehingga 127.0.0.1 bisa menjangkaunya. Itulah penyiapan CAPTCHA notebook Jupyter yang umum, tetapi bukan satu-satunya. Notebook yang disajikan JupyterHub di sebuah server, kernel jarak jauh di VS Code, atau notebook yang di-host seperti Google Colab menjalankan sel Anda di tempat lain, dan di sana 127.0.0.1 berarti mesin itu sendiri. Pemanggilan pertama lalu gagal dengan NetworkException dan koneksi yang ditolak. Alihkan CapSkip ke mode Server di pengaturan koneksi dan ia akan mendengarkan di alamat jaringan atau IP publik Anda, sehingga kernel jarak jauh memanggilnya melalui API yang sama dengan alamat itu sebagai host.
Gunakan IP publik statis jika rutenya melewati internet. CapSkip membuka port-nya untuk semua alamat saat mode Server dimulai, jadi untuk membatasinya hanya pada mesin yang Anda harapkan, tambahkan aturan blokir Windows Firewall untuk alamat lainnya. Cara itu berhasil jika alamat kernel tetap, seperti pada server JupyterHub milik Anda sendiri. Alamat keluar notebook yang di-host bisa berubah antar sesi, jadi untuk notebook semacam itu, aktifkan validasi API key di pengaturan CapSkip dan berikan key-nya sebagai apiKey. Perangkatnya tetap milik Anda sendiri dan tetap tanpa kuota. Klien tidak membaca variabel lingkungan apa pun dengan sendirinya, jadi baca CAPSKIP_HOST dengan os.getenv di sebuah sel lalu teruskan ke klien, seperti yang dilakukan contoh lengkap.
Contoh lengkap yang berfungsi
Tiga sel, semuanya async: alur kerja CAPTCHA notebook Jupyter lengkap yang paling singkat dan tetap bertahan saat tombol stop ditekan.
# Cell 1: pip install capskip requests beautifulsoup4, then restart the kernel. %pip install capskip requests beautifulsoup4
# Cell 2: the client and a helper. Run once per kernel.
import os
from urllib.parse import urljoin
import requests
from bs4 import BeautifulSoup
from capskip import AsyncCapSkip, CapSkipError
PAGE_URL = "https://example.com/login"
solver = AsyncCapSkip(
apiKey=os.getenv("CAPSKIP_API_KEY", "capskip"),
host=os.getenv("CAPSKIP_HOST", "127.0.0.1"),
port=int(os.getenv("CAPSKIP_PORT", "8080")),
pollingInterval=1,
)
def form_fields(form):
fields = {}
for tag in form.select("input[name]"):
kind = (tag.get("type") or "text").lower()
if kind in ("submit", "button", "image", "file", "reset"):
continue
if kind in ("checkbox", "radio") and not tag.has_attr("checked"):
continue
fields[tag["name"]] = tag.get("value", "on" if kind in ("checkbox", "radio") else "")
return fields# Cell 3: fetch, solve, post. Run it again for a fresh token.
session = requests.Session()
page = session.get(PAGE_URL, timeout=30)
soup = BeautifulSoup(page.text, "html.parser")
widget = soup.select_one(".g-recaptcha[data-sitekey]")
if widget is None:
raise RuntimeError("No reCAPTCHA widget in the HTML; the page may build it with JavaScript.")
form = widget.find_parent("form")
try:
result = await solver.recaptcha(sitekey=widget["data-sitekey"], url=PAGE_URL)
except CapSkipError as err:
raise RuntimeError(f"solve failed: {type(err).__name__}: {err}") from err
data = form_fields(form)
data["username"] = "YOUR_USERNAME"
data["g-recaptcha-response"] = result["code"]
res = session.post(urljoin(PAGE_URL, form.get("action") or PAGE_URL), data=data,
headers={"Referer": PAGE_URL}, timeout=30)
print(res.status_code)Sel 3 adalah sel yang Anda jalankan ulang, dan setiap eksekusi berarti pemecahan baru dan token baru, karena token reCAPTCHA hanya berlaku sekali. Jika halaman membangun widget-nya dari JavaScript, HTML yang diambil tidak memiliki sitekey; gunakan sel Playwright dari Langkah 4 sebagai gantinya, atau baca sitekey dari skrip yang merendernya.
Kesalahan umum dan artinya
| Apa yang Anda lihat | Penyebab | Perbaiki |
|---|---|---|
| RuntimeError: asyncio.run() cannot be called from a running event loop | Kernel sudah menjalankan event loop | Lakukan await pada pemanggilan di level teratas sel |
| RuntimeError: This event loop is already running | run_until_complete dipanggil pada loop milik kernel itu sendiri | Lakukan await pada pemanggilan di level teratas sel |
| Playwright menyatakan Anda memakai Sync API di dalam loop asyncio | API sinkron menolak berjalan selama ada loop yang sedang berjalan | Gunakan playwright.async_api dengan await; pada ipykernel 7.4 atau lebih baru, menjalankan kode sinkron di worker thread juga berfungsi |
| NotImplementedError dari chromium.launch() di Windows | ipykernel sebelum 7.4.0 menjalankan sel pada selector loop, yang tidak bisa memulai proses browser | Jalankan %pip install -U ipykernel, lalu mulai ulang kernel |
| ModuleNotFoundError untuk capskip, atau versi yang lebih lama daripada yang Anda instal | pip milik shell menginstal ke Python yang berbeda dari Python milik kernel | Instal dengan %pip dan periksa sys.executable |
| Tombol stop tidak berpengaruh dan sel terus berjalan | Klien sinkron sedang menunggu CapSkip yang sudah menerima koneksi tetapi tidak pernah menjawab, dan klien itu tidak menyetel timeout HTTP | Tutup CapSkip atau mulai ulang kernel, dan utamakan AsyncCapSkip di notebook |
| TypeError tentang weak reference pada setiap pemanggilan httpx atau AsyncCapSkip, Python 3.14 | nest_asyncio diterapkan di sel sebelumnya | Mulai ulang kernel dan buang nest_asyncio; top-level await tidak membutuhkan patch |
| NetworkException dengan koneksi yang ditolak | CapSkip tidak berjalan, atau kernel berjalan di mesin lain | Jalankan CapSkip, atau alihkan ke mode Server dan berikan alamatnya |
| ApiException dengan ERROR_CAPTCHA_UNSOLVABLE | CapSkip menggagalkan pemecahan, misalnya setelah menunggu 250 detik untuk mendapat thread kosong | Samakan ukuran batch dengan Max. Threads, tambahkan proxy, lalu coba lagi |
| Situs menolak token yang dikembalikan CapSkip | Form dikirim tanpa cookie halaman, field tersembunyinya, atau Referer, atau token sudah berumur lebih dari dua menit | Kirim melalui requests.Session yang sama dengan form_fields dan Referer, tepat setelah pemecahan |
FAQ
Apakah ini berfungsi di JupyterLab dan notebook VS Code?
Ya. JupyterLab, Notebook 7, dan editor notebook di VS Code semuanya menyerahkan sel Anda ke ipykernel, sehingga top-level await, error asyncio.run, dan event loop Windows berperilaku sama di ketiganya. Yang berbeda adalah Python mana yang dipakai kernel, jadi periksa sys.executable di editor mana pun yang Anda buka.
Bisakah notebook yang di-host seperti Google Colab memakai pemecah CAPTCHA di PC saya?
Bisa, melalui mode Server. Notebook yang di-host menjalankan kernel-nya di mesin milik penyedia layanan, jadi 127.0.0.1 di sana bukan PC Anda. Alihkan CapSkip ke mode Server di pengaturan koneksi, beri PC Anda IP publik statis, aktifkan validasi API key, lalu berikan alamat dan key Anda ke klien. Alamat keluar notebook yang di-host bisa berubah, jadi key itulah yang mencegah orang asing masuk; aturan blokir Windows Firewall tetap bisa menutup port untuk rentang alamat yang tidak pernah Anda pakai. Pemecah CAPTCHA tetap berada di perangkat milik Anda, jadi sesi panjang berisi banyak eksekusi ulang tidak pernah mengubah biaya yang Anda bayar.
Haruskah saya memakai nest_asyncio agar asyncio.run berfungsi?
Tidak. Pustaka itu mem-patch loop yang sedang berjalan agar asyncio.run bisa bersarang di dalamnya, dan dulu itu menjadi perbaikan umum untuk error ini. Proyeknya sudah diarsipkan, dan di Python 3.14 patch itu merusak setiap pemanggilan httpx berikutnya di kernel, termasuk AsyncCapSkip. Top-level await sudah melakukan apa yang Anda inginkan dari asyncio.run, tanpa mengubah apa pun pada loop.
Apa yang terjadi pada pemecahan ketika saya menginterupsi sel?
Sel Anda berhenti dan CapSkip tetap bekerja. SDK tidak punya pemanggilan untuk membatalkan job, jadi CapSkip menyelesaikan pemecahan dan tidak ada yang membaca token-nya. Menjalankan sel itu lagi akan mengirim job baru. Jika Anda menginterupsi batch yang besar, pemecahan yang ditinggalkan membuat thread CapSkip tetap sibuk sampai setiap pemecahan selesai atau terkena timeout milik CapSkip sendiri, yang bisa memakan waktu beberapa menit, sehingga batch baru yang langsung dimulai harus menunggu di belakangnya.
Versi singkatnya
Pemecahan CAPTCHA di notebook Jupyter bermuara pada lima kebiasaan. Instal dengan %pip, jangan pernah lewat shell. Klien CapSkip sinkron bekerja di dalam sel seperti di skrip; setel pollingInterval ke 1 agar interupsi cepat masuk. Untuk async, lakukan await pada AsyncCapSkip di level teratas sel dan jangan pernah membungkusnya dengan asyncio.run atau beralih ke nest_asyncio. Untuk browser, gunakan Selenium apa adanya atau API async milik Playwright, dan di Windows jalankan ipykernel 7.4 atau lebih baru. Ketika kernel berada di mesin lain, alihkan CapSkip ke mode Server dan berikan alamatnya.
- Setiap tipe CAPTCHA yang dipecahkan paket Python: halaman pemecah CAPTCHA Python.
- Cara kerja widget itu sendiri dan apa saja yang dicakup pemecah CAPTCHA: halaman pemecah reCAPTCHA v2.
Di notebook, sebuah scraper dibangun secara bertahap, dari satu eksekusi ulang ke eksekusi ulang berikutnya. Dengan bypass captcha yang berjalan di mesin Anda sendiri, setiap eksekusi ulang itu gratis.
