Kabar baik untuk siapa pun yang mengotomatiskan pencarian data publik: mayoritas portal pemerintah masih memakai Image dan OCR CAPTCHA model lama — teks terdistorsi atau kode numerik — dan justru tipe inilah yang paling mudah ditangani lewat satu panggilan API. Polanya selalu sama: unduh gambar CAPTCHA, kirim ke endpoint OCR CaptchaAI dengan method=base64, lalu pakai teksnya untuk melanjutkan pencarian. Artikel ini menerapkannya untuk catatan pengadilan, properti, badan usaha, sampai pengajuan UCC.
Alur empat langkah yang dipakai ulang di tiap portal
Apa pun jenis CAPTCHA-nya, seluruh kode di sini mengikuti frame yang sama. Hafalkan empat langkah ini dan sisanya tinggal menyesuaikan parameter:
- Kirim gambar CAPTCHA ke
in.phpdenganmethod=base64. - Simpan task ID yang dikembalikan pada respons pertama.
- Lakukan polling ke
res.phpsampaistatusbernilai 1. - Pakai teks hasil solve untuk mengisi field formulir, lalu kirim pencarian.
Karena pola ini stabil di semua tipe, menambah dukungan untuk portal baru biasanya cukup mengganti selector gambar dan nama field formulirnya.
CAPTCHA apa yang muncul di tiap jenis portal
Bentuk CAPTCHA berbeda-beda tergantung kategori portal. Tabel berikut memetakan apa yang biasanya Anda temui:
| Kategori portal | CAPTCHA yang khas | Contoh tantangan |
|---|---|---|
| Pencarian kasus pengadilan | CAPTCHA teks khusus | Alfanumerik 5–6 karakter terdistorsi |
| Catatan properti daerah | CAPTCHA matematika | "Berapa 4 + 7?" |
| Pencarian badan usaha | Teks gambar CAPTCHA | Huruf melengkung dengan noise garis |
| Catatan penting | reCAPTCHA v2 | Pemilihan kisi gambar |
| Izin mendirikan bangunan | CAPTCHA teks sederhana | Kode numerik 4 digit |
| Pengajuan UCC | CAPTCHA OCR khusus | Campuran huruf besar-kecil dengan noise latar |
Membangun modul pencarian dengan penyelesaian CAPTCHA
Kelas berikut memuat halaman pencarian, mendeteksi apakah ada gambar CAPTCHA, menyelesaikannya lewat OCR, lalu mengirim formulir. Alur intinya konsisten: muat sesi → ambil gambar → solve → kirim.
Mendeteksi gambar CAPTCHA di halaman
Selector di _extract_captcha_url mencoba beberapa pola img yang umum di portal lama, sehingga satu kelas bisa dipakai untuk banyak situs tanpa hardcode per portal.
import requests
import base64
import time
from urllib.parse import urljoin
class PublicRecordsSearcher:
def __init__(self, api_key):
self.api_key = api_key
self.session = requests.Session()
self.session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
})
def search_court_records(self, portal_url, case_number):
"""Search court records, solving image CAPTCHAs as needed."""
# Load the search page
page = self.session.get(f"{portal_url}/search")
# Extract CAPTCHA image
captcha_img_url = self._extract_captcha_url(page.text, portal_url)
if not captcha_img_url:
# No CAPTCHA on this page
return self._submit_search(portal_url, case_number)
# Download and solve CAPTCHA
img_response = self.session.get(captcha_img_url)
captcha_text = self._solve_image_captcha(img_response.content)
# Submit search with solved CAPTCHA
return self._submit_search(portal_url, case_number, captcha_text)
def _extract_captcha_url(self, html, base_url):
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, "html.parser")
# Look for common CAPTCHA image patterns
captcha_img = (
soup.find("img", {"id": "captchaImage"}) or
soup.find("img", {"class": "captcha"}) or
soup.find("img", attrs={"src": lambda s: s and "captcha" in s.lower()})
)
if captcha_img and captcha_img.get("src"):
return urljoin(base_url, captcha_img["src"])
return None
def _solve_image_captcha(self, image_bytes):
img_base64 = base64.b64encode(image_bytes).decode("utf-8")
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": self.api_key,
"method": "base64",
"body": img_base64,
"json": 1
})
task_id = resp.json()["request"]
for _ in range(30):
time.sleep(3)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": self.api_key,
"action": "get",
"id": task_id,
"json": 1
})
data = result.json()
if data["status"] == 1:
return data["request"]
raise TimeoutError("CAPTCHA solve timed out")
def _submit_search(self, portal_url, case_number, captcha_text=None):
form_data = {"caseNumber": case_number}
if captcha_text:
form_data["captcha"] = captcha_text
response = self.session.post(
f"{portal_url}/search/results",
data=form_data
)
return response.text
# Usage
searcher = PublicRecordsSearcher("YOUR_API_KEY")
results = searcher.search_court_records(
"https://courts.example.gov",
"2024-CV-12345"
)
Menangani CAPTCHA matematika
Sebagian portal daerah menampilkan soal seperti "4 + 7 = ?". CaptchaAI memperlakukannya sebagai pengenalan teks: kirim gambar dengan parameter textinstructions agar worker mengembalikan hanya angkanya.
def solve_math_captcha(self, image_bytes):
"""Solve math CAPTCHAs like '4 + 7 = ?'"""
img_base64 = base64.b64encode(image_bytes).decode("utf-8")
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": self.api_key,
"method": "base64",
"body": img_base64,
"textinstructions": "solve the math equation and return only the number",
"json": 1
})
task_id = resp.json()["request"]
# Poll for result
for _ in range(30):
time.sleep(3)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": self.api_key,
"action": "get",
"id": task_id,
"json": 1
})
data = result.json()
if data["status"] == 1:
return data["request"]
raise TimeoutError("Math CAPTCHA solve timed out")
Pencarian lintas portal dengan JavaScript (Node.js)
Untuk menyapu beberapa portal dalam satu proses, agregator berikut menelusuri tiap portal berurutan, menyelesaikan CAPTCHA gambar bila muncul, dan mencatat error per portal tanpa menghentikan yang lain.
Menampung hasil dan error per portal
Setiap portal dibungkus try/catch, jadi satu portal yang menolak permintaan tidak menggagalkan seluruh batch — hasil dan error terkumpul berdampingan.
class RecordsAggregator {
constructor(apiKey) {
this.apiKey = apiKey;
}
async searchAcrossPortals(query, portals) {
const results = [];
for (const portal of portals) {
try {
const data = await this.searchPortal(portal, query);
results.push({ portal: portal.name, records: data });
} catch (error) {
results.push({ portal: portal.name, error: error.message });
}
}
return results;
}
async searchPortal(portal, query) {
const pageResponse = await fetch(portal.searchUrl);
const html = await pageResponse.text();
// Check for image CAPTCHA
const captchaMatch = html.match(/captcha[^"]*\.(?:png|jpg|gif)/i);
let captchaAnswer = null;
if (captchaMatch) {
const imgUrl = new URL(captchaMatch[0], portal.searchUrl).href;
const imgData = await fetch(imgUrl);
const buffer = await imgData.arrayBuffer();
const base64 = Buffer.from(buffer).toString('base64');
captchaAnswer = await this.solveImageCaptcha(base64);
}
// Submit search
const formData = new URLSearchParams({ q: query });
if (captchaAnswer) formData.append('captcha', captchaAnswer);
const response = await fetch(portal.searchUrl, {
method: 'POST',
body: formData
});
return response.text();
}
async solveImageCaptcha(base64Image) {
const submitResp = await fetch('https://ocr.captchaai.com/in.php', {
method: 'POST',
body: new URLSearchParams({
key: this.apiKey,
method: 'base64',
body: base64Image,
json: '1'
})
});
const { request: taskId } = await submitResp.json();
for (let i = 0; i < 30; i++) {
await new Promise(r => setTimeout(r, 3000));
const result = await fetch(
`https://ocr.captchaai.com/res.php?key=${this.apiKey}&action=get&id=${taskId}&json=1`
);
const data = await result.json();
if (data.status === 1) return data.request;
}
throw new Error('CAPTCHA solve timed out');
}
}
// Usage
const aggregator = new RecordsAggregator('YOUR_API_KEY');
const results = await aggregator.searchAcrossPortals('Smith LLC', [
{ name: 'State Business Registry', searchUrl: 'https://sos.example.gov/search' },
{ name: 'County Court Records', searchUrl: 'https://courts.example.gov/search' }
]);
Parameter OCR untuk portal pemerintah
Beberapa parameter kecil menentukan akurasi pada CAPTCHA portal pemerintah:
| Parameter | Nilai | Kapan dipakai |
|---|---|---|
method |
base64 |
Gambar diunduh sebagai byte |
method |
post |
Kirim file gambar secara langsung |
language |
0 |
Teks CAPTCHA berbahasa Inggris/Latin |
numeric |
1 |
CAPTCHA khusus angka |
min_len / max_len |
Bervariasi | Ketika jumlah karakter bisa diprediksi |
textinstructions |
Perintah khusus | CAPTCHA matematika atau format tertentu |
Mengatasi masalah yang sering muncul
| Masalah | Penyebab | Solusi |
|---|---|---|
| Gambar CAPTCHA membalas 403 | Cookie sesi belum ada | Muat halaman pencarian dulu, baru ambil gambarnya |
| Jawaban CAPTCHA salah | Kualitas gambar rendah | Praproses gambar — naikkan kontras, hilangkan noise (panduan pra-pemrosesan gambar) |
| CAPTCHA ter-refresh saat submit | Token formulir kedaluwarsa | Ekstrak kolom hidden formulir bersama gambar CAPTCHA |
| Hasil pencarian kosong setelah CAPTCHA | POST kehilangan cookie karena redirect | Pakai allow_redirects=True dan pertahankan sesi |
Kepatuhan untuk tim data di Indonesia
Banyak pekerjaan scraping data publik di Indonesia berjalan di infrastruktur regional seperti AWS ap-southeast-3 (Jakarta). Makin dekat worker ke portal target, makin kecil batas waktu yang perlu Anda longgarkan dan makin jarang solve gagal karena jaringan.
Catatan kepatuhan: sesuai UU Pelindungan Data Pribadi (UU 27/2022), olah hanya data yang boleh Anda proses dan hindari data pribadi tanpa dasar yang sah. CAPTCHA hanya menangani verifikasi otomatis, bukan izin akses. Bagian ini bukan nasihat hukum.
Pertanyaan umum
Apakah CaptchaAI menangani reCAPTCHA v2 yang dipakai sebagian portal catatan penting?
Ya. Selain Image dan OCR CAPTCHA, CaptchaAI mendukung reCAPTCHA v2, jadi portal yang sudah pindah ke pemilihan kisi gambar tetap bisa Anda otomatiskan — hanya submission method-nya yang berbeda.
Berapa biaya untuk memproses ribuan pencarian per bulan?
Harga CaptchaAI berbasis thread, bukan per solve: Anda membayar jumlah thread bersamaan dengan solve tak terbatas per thread, tanpa biaya per-CAPTCHA. Pipeline kecil cukup dengan BASIC ($15/bulan, 5 thread); untuk pencarian paralel lintas banyak portal, naik ke ADVANCE ($90/bulan, 50 thread).
Kenapa CAPTCHA ter-refresh setiap kali formulir saya kirim?
Biasanya karena token formulir tersembunyi kedaluwarsa sebelum jawaban terkirim. Ambil semua kolom hidden (termasuk token anti-CSRF) pada permintaan yang sama saat Anda mengunduh gambar CAPTCHA, lalu kirim seluruhnya bersama hasil solve dalam satu POST.
Apakah boleh mengotomatiskan pencarian data publik?
Selama Anda mengakses catatan yang terbuka untuk umum dan tidak mengumpulkan data pribadi tanpa dasar yang sah, otomatisasi pencarian umumnya wajar. Tetap ikuti UU Pelindungan Data Pribadi (UU 27/2022) dan proses hanya data yang boleh Anda olah.
Langkah selanjutnya
Otomatiskan pencarian data publik Anda: ambil kunci API CaptchaAI lalu tangani CAPTCHA portal pemerintah dengan pola di atas.