Kunci menyelesaikan CAPTCHA gambar di situs Jepang dan Korea sebenarnya cuma satu parameter: kirim gambar ke endpoint OCR CaptchaAI dengan language=2. Parameter itu memindahkan pengenalan dari model Latin ke model karakter CJK, sehingga hiragana, katakana, kanji, dan hangul terbaca sebagai teks, bukan coretan acak.
Sisanya adalah hal yang biasa merusak integrasi di produksi: encoding respons yang salah, sesi yang keburu kedaluwarsa, dan salah menebak tipe CAPTCHA di halaman target. Tiga hal itu yang dibahas di sini, lengkap dengan contoh Python dan Node.js yang siap dijalankan.
Kenapa OCR biasa gagal pada karakter Jepang dan Korea
Mesin OCR Latin mengasumsikan jumlah simbol yang kecil dengan bentuk yang saling berbeda. Asumsi itu runtuh pada karakter CJK: hiragana dan katakana punya banyak pasangan yang nyaris identik saat gambar dikaburkan, kanji punya ribuan bentuk bergoresan padat, dan satu blok hangul sebenarnya gabungan beberapa huruf.
Akibatnya pipeline OCR generik mengembalikan string kosong atau karakter Latin acak. Yang dibutuhkan adalah model yang dilatih pada rangkaian karakter tersebut - itulah yang diaktifkan language=2 di API CaptchaAI.
Peta tipe CAPTCHA di situs Jepang dan Korea
Pastikan tipe tantangannya sebelum menulis kode; salah menebak di sini berarti task Anda dikirim ke solver yang keliru.
| Wilayah | Tipe yang umum ditemui | Kumpulan karakter | Penanganan di CaptchaAI |
|---|---|---|---|
| Jepang | CAPTCHA gambar hiragana/katakana/kanji, reCAPTCHA v2 dan v3 | hiragana, katakana, kanji, Latin | Image/OCR dengan language=2, atau solver reCAPTCHA |
| Korea | CAPTCHA gambar hangul, reCAPTCHA v2 dan v3, slider buatan platform | hangul, Latin | Image/OCR dengan language=2, atau solver reCAPTCHA |
| Keduanya | reCAPTCHA dengan antarmuka yang dilokalkan | tidak relevan (berbasis token) | solver reCAPTCHA memakai sitekey dari halaman |
Dua catatan jujur sebelum Anda merancang alur. Pertama, hCaptcha dan FunCaptcha memang muncul di sebagian situs Jepang dan Korea, tetapi keduanya belum didukung CaptchaAI - untuk tipe itu Anda memerlukan layanan lain. Kedua, GeeTest v3 didukung, sedangkan GeeTest v4 masih segera hadir; slider berpemilik buatan platform lokal bukan tipe standar dan perlu diuji satu per satu.
Contoh Python: gambar Jepang dan sesi Korea
Alurnya sama seperti integrasi CaptchaAI lain: kirim, simpan task ID, polling, lalu pakai hasilnya. Yang berbeda hanya language=2 dan cara mengambil gambarnya. Di situs Korea, gambar CAPTCHA sering terikat ke sesi, jadi ambil gambar dengan requests.Session() yang sama dengan yang nanti mengirim form.
import requests
import base64
import time
API_KEY = "YOUR_API_KEY"
SUBMIT_URL = "https://ocr.captchaai.com/in.php"
RESULT_URL = "https://ocr.captchaai.com/res.php"
def solve_japanese_captcha(image_path: str) -> str:
"""Solve a Japanese character image CAPTCHA."""
with open(image_path, "rb") as f:
image_b64 = base64.b64encode(f.read()).decode()
resp = requests.post(SUBMIT_URL, data={
"key": API_KEY,
"method": "base64",
"body": image_b64,
"language": 2, # CJK character support
"json": 1,
}, timeout=30).json()
if resp.get("status") != 1:
raise RuntimeError(f"Submit: {resp.get('request')}")
task_id = resp["request"]
for _ in range(24):
time.sleep(5)
poll = requests.get(RESULT_URL, params={
"key": API_KEY, "action": "get", "id": task_id, "json": 1,
}, timeout=15).json()
if poll.get("request") == "CAPCHA_NOT_READY":
continue
if poll.get("status") == 1:
return poll["request"]
raise RuntimeError(f"Solve: {poll.get('request')}")
raise RuntimeError("Timeout")
def solve_korean_captcha(image_path: str) -> str:
"""Solve a Korean hangul image CAPTCHA."""
with open(image_path, "rb") as f:
image_b64 = base64.b64encode(f.read()).decode()
resp = requests.post(SUBMIT_URL, data={
"key": API_KEY,
"method": "base64",
"body": image_b64,
"language": 2,
"json": 1,
}, timeout=30).json()
if resp.get("status") != 1:
raise RuntimeError(f"Submit: {resp.get('request')}")
task_id = resp["request"]
for _ in range(24):
time.sleep(5)
poll = requests.get(RESULT_URL, params={
"key": API_KEY, "action": "get", "id": task_id, "json": 1,
}, timeout=15).json()
if poll.get("request") == "CAPCHA_NOT_READY":
continue
if poll.get("status") == 1:
return poll["request"]
raise RuntimeError(f"Solve: {poll.get('request')}")
raise RuntimeError("Timeout")
def solve_captcha_from_session(session: requests.Session,
captcha_url: str,
language: int = 2) -> str:
"""Download and solve a CAPTCHA within a session context."""
resp = session.get(captcha_url, timeout=15)
image_b64 = base64.b64encode(resp.content).decode()
submit = requests.post(SUBMIT_URL, data={
"key": API_KEY,
"method": "base64",
"body": image_b64,
"language": str(language),
"json": 1,
}, timeout=30).json()
if submit.get("status") != 1:
raise RuntimeError(f"Submit: {submit.get('request')}")
task_id = submit["request"]
for _ in range(24):
time.sleep(5)
poll = requests.get(RESULT_URL, params={
"key": API_KEY, "action": "get", "id": task_id, "json": 1,
}, timeout=15).json()
if poll.get("request") == "CAPCHA_NOT_READY":
continue
if poll.get("status") == 1:
return poll["request"]
raise RuntimeError(f"Solve: {poll.get('request')}")
raise RuntimeError("Timeout")
# --- Usage ---
# Japanese CAPTCHA
jp_text = solve_japanese_captcha("japanese_captcha.png")
print(f"Japanese CAPTCHA: {jp_text}")
# Korean CAPTCHA from a live session
session = requests.Session()
session.headers["Accept-Language"] = "ko-KR,ko;q=0.9"
session.get("https://example.kr/login") # establish session
kr_text = solve_captcha_from_session(session, "https://example.kr/captcha/image")
print(f"Korean CAPTCHA: {kr_text}")
Perhatikan header Accept-Language pada contoh terakhir: sebagian situs menyajikan varian gambar berbeda per bahasa antarmuka, dan konsistensi header memastikan gambar yang Anda selesaikan sama dengan yang divalidasi server.
Contoh Node.js: satu fungsi untuk kedua bahasa
Di Node.js tidak perlu dua fungsi terpisah untuk Jepang dan Korea. Deteksi bahasa terjadi di sisi model, jadi satu helper cukup.
const API_KEY = "YOUR_API_KEY";
const SUBMIT_URL = "https://ocr.captchaai.com/in.php";
const RESULT_URL = "https://ocr.captchaai.com/res.php";
const fs = require("fs");
async function solveAsianCaptcha(imagePath) {
const imageB64 = fs.readFileSync(imagePath, "base64");
const body = new URLSearchParams({
key: API_KEY,
method: "base64",
body: imageB64,
language: "2",
json: "1",
});
const resp = await (await fetch(SUBMIT_URL, { method: "POST", body })).json();
if (resp.status !== 1) throw new Error(`Submit: ${resp.request}`);
const taskId = resp.request;
for (let i = 0; i < 24; i++) {
await new Promise((r) => setTimeout(r, 5000));
const url = `${RESULT_URL}?key=${API_KEY}&action=get&id=${taskId}&json=1`;
const poll = await (await fetch(url)).json();
if (poll.request === "CAPCHA_NOT_READY") continue;
if (poll.status === 1) return poll.request;
throw new Error(`Solve: ${poll.request}`);
}
throw new Error("Timeout");
}
async function solveFromUrl(captchaUrl, cookies = "") {
const resp = await fetch(captchaUrl, {
headers: { Cookie: cookies, "Accept-Language": "ja-JP,ja;q=0.9" },
});
const buffer = await resp.arrayBuffer();
const imageB64 = Buffer.from(buffer).toString("base64");
const body = new URLSearchParams({
key: API_KEY, method: "base64", body: imageB64,
language: "2", json: "1",
});
const submitResp = await (await fetch(SUBMIT_URL, { method: "POST", body })).json();
if (submitResp.status !== 1) throw new Error(`Submit: ${submitResp.request}`);
const taskId = submitResp.request;
for (let i = 0; i < 24; i++) {
await new Promise((r) => setTimeout(r, 5000));
const url = `${RESULT_URL}?key=${API_KEY}&action=get&id=${taskId}&json=1`;
const poll = await (await fetch(url)).json();
if (poll.request === "CAPCHA_NOT_READY") continue;
if (poll.status === 1) return poll.request;
throw new Error(`Solve: ${poll.request}`);
}
throw new Error("Timeout");
}
// Usage
const jpText = await solveAsianCaptcha("japanese_captcha.png");
console.log(`Japanese: ${jpText}`);
Karakteristik tiap sistem penulisan
Skala tiap sistem penulisan menentukan kualitas gambar yang perlu Anda kirim.
| Sistem penulisan | Skala | Yang perlu diperhatikan |
|---|---|---|
| Hiragana | 46 karakter dasar | Fonetik, untuk kata asli Jepang; banyak bentuk mirip saat gambar dikaburkan |
| Katakana | 46 karakter dasar | Fonetik, untuk kata serapan; paling sering tertukar dengan hiragana |
| Kanji | ribuan karakter | CAPTCHA umumnya memakai subset yang sering dipakai sehari-hari |
| Hangul | 24 huruf dasar, sekitar 11.000 blok suku kata | Satu blok visual berisi beberapa huruf sekaligus |
| Campuran (Jepang) | tiga sistem plus Latin dalam satu gambar | Kasus paling berat; kirim resolusi tertinggi yang tersedia |
Masalah yang sering muncul dan cara menanganinya
| Gejala | Penyebab | Penanganan |
|---|---|---|
| Hiragana tertukar dengan katakana | Bentuk visual yang berdekatan | Pastikan language=2 benar-benar terkirim di body request, bukan hanya tertulis di komentar kode |
| Teks hangul kembali sebagai karakter aneh | Respons dibaca sebagai Latin-1, bukan UTF-8 | Paksa encoding: response.encoding = 'utf-8' sebelum membaca isinya |
| Gambar skrip campuran sering meleset | Beberapa sistem penulisan dalam satu gambar kecil | Ambil gambar pada resolusi asli, bukan hasil screenshot yang sudah diperkecil |
| Akurasi turun pada teks bergaya | Distorsi dan garis pengganggu yang tebal | Minta gambar versi baru dan kirim ulang, daripada membersihkannya sendiri |
| Sesi kedaluwarsa setelah hasil kembali | Jeda terlalu lama antara membuka halaman dan mengirim form | Bentuk sesi lebih dulu, kirim CAPTCHA segera, lalu submit tanpa jeda tambahan |
Respons ERROR_ZERO_BALANCE |
Saldo atau paket thread habis | Cek dashboard dan pastikan thread aktif cukup untuk beban paralel Anda |
Untuk CAPTCHA gambar, SLA waktu penyelesaian CaptchaAI adalah <0.5 detik. Kalau angka yang Anda amati jauh lebih lama, penyebabnya hampir selalu di sisi klien: dengan interval polling 5 detik, hasil baru terambil pada polling berikutnya, bukan tepat saat siap.
Catatan praktis untuk tim di Indonesia
Banyak pekerjaan monitoring harga dan riset pasar Jepang-Korea dari Indonesia berjalan sebagai proyek kontrak: margin tipis, volume naik-turun. Dua hal paling berpengaruh.
- Lokasi deploy. Worker di AWS
ap-southeast-1(Singapura) atauap-southeast-3(Jakarta) memangkas latensi ke target Asia Timur dibanding region Eropa. Latensi ini terpisah dari waktu penyelesaian CAPTCHA, tetapi ikut menentukan umur sesi Anda. - Model biaya. CaptchaAI menagih per thread bersamaan, bukan per solve, dengan solve tanpa batas per thread. Untuk satu worker uji coba, BASIC ($15/bulan, 5 thread) cukup; untuk beberapa pipeline scraping paralel, STANDARD ($30/bulan, 15 thread) atau ADVANCE ($90/bulan, 50 thread) lebih masuk akal. Karena biayanya tetap, lonjakan volume tidak mengubah tagihan.
Satu catatan kepatuhan yang relevan: UU Pelindungan Data Pribadi (UU 27/2022) berlaku atas data pribadi yang Anda proses, dari mana pun sumbernya. Ambil hanya data yang memang boleh Anda proses, dan hindari halaman di balik login milik orang lain.
Pertanyaan umum
Berapa lama waktu penyelesaian CAPTCHA gambar Jepang atau Korea?
SLA CaptchaAI untuk CAPTCHA gambar adalah <0.5 detik. Waktu yang terasa di aplikasi biasanya lebih lama karena interval polling; contoh di atas memakai jeda 5 detik. Perkecil jeda pada polling pertama jika Anda butuh respons lebih gesit.
Bagaimana dengan hCaptcha dan slider buatan platform Korea?
Belum. hCaptcha dan FunCaptcha tidak didukung saat ini, dan slider berpemilik buatan platform tertentu bukan tipe standar. Yang didukung untuk pasar ini adalah CAPTCHA gambar (Image/OCR), grid image, seluruh keluarga reCAPTCHA, GeeTest v3, serta Cloudflare Turnstile dan Cloudflare Challenge.
Kenapa hasil hangul saya muncul sebagai karakter berantakan?
Hampir selalu masalah encoding di sisi klien, bukan di sisi solver. Pastikan respons dibaca sebagai UTF-8, kolom database memakai charset yang mendukung karakter CJK, dan terminal atau file log tidak memaksa encoding lama.
Berapa thread yang saya butuhkan untuk ribuan CAPTCHA per hari?
Yang menentukan bukan jumlah per hari, melainkan berapa banyak yang berjalan bersamaan. Satu thread berarti satu CAPTCHA sedang diproses; begitu selesai, thread itu langsung dipakai task berikutnya. Hitung dari jumlah worker paralel Anda, lalu pilih paket dengan thread sebanyak itu atau sedikit lebih longgar.
Artikel terkait
Langkah selanjutnya
Uji satu gambar CJK milik Anda sendiri sebelum membangun pipeline penuh: ambil API key CaptchaAI, kirim satu gambar dengan language=2, lalu bandingkan hasilnya dengan teks yang Anda baca sendiri.
Panduan lain yang berkaitan: