Platform perbandingan asuransi dan halaman penawaran harga operator melindungi mesin tarif mereka dengan CAPTCHA untuk mencegah pengambilan penawaran harga secara otomatis. CaptchaAI menangani tantangan ini untuk tim QA yang menguji alur kerja asuransi dan agregator perbandingan.
CAPTCHA di Situs Asuransi
| Jenis Asuransi | CAPTCHA | Titik Pemicu | Kompleksitas Form |
|---|---|---|---|
| Asuransi mobil | reCAPTCHA v2 | Submit form penawaran | Multi-step (kendaraan + pengemudi) |
| Asuransi kesehatan | reCAPTCHA v2 | Perbandingan paket | Multi-step (demografi) |
| Asuransi rumah | Image CAPTCHA | Pencarian alamat | Sedang |
| Asuransi jiwa | reCAPTCHA v2 | Kalkulator nilai | Form sederhana |
| Asuransi perjalanan | reCAPTCHA v2 Invisible | Permintaan penawaran | Form sederhana |
| Asuransi bisnis | reCAPTCHA v3 | Hubungi/form penawaran | Form panjang |
Kolektor Kutipan Multi-Pembawa
import requests
import time
import re
import base64
CAPTCHAAI_KEY = "YOUR_API_KEY"
CAPTCHAAI_URL = "https://ocr.captchaai.com"
def solve_recaptcha(sitekey, pageurl):
resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data={
"key": CAPTCHAAI_KEY, "method": "userrecaptcha",
"googlekey": sitekey, "pageurl": pageurl, "json": 1,
})
task_id = resp.json()["request"]
for _ in range(60):
time.sleep(5)
result = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
"key": CAPTCHAAI_KEY, "action": "get",
"id": task_id, "json": 1,
})
data = result.json()
if data["request"] != "CAPCHA_NOT_READY":
return data["request"]
raise TimeoutError("Timeout")
def solve_image_captcha(image_bytes):
img_b64 = base64.b64encode(image_bytes).decode()
resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data={
"key": CAPTCHAAI_KEY, "method": "base64",
"body": img_b64, "json": 1,
})
task_id = resp.json()["request"]
for _ in range(20):
time.sleep(3)
result = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
"key": CAPTCHAAI_KEY, "action": "get",
"id": task_id, "json": 1,
})
data = result.json()
if data["request"] != "CAPCHA_NOT_READY":
return data["request"]
raise TimeoutError("Timeout")
class InsuranceQuoteCollector:
def __init__(self, proxy=None):
self.session = requests.Session()
if proxy:
self.session.proxies = {"http": proxy, "https": proxy}
self.session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 Chrome/126.0.0.0 Safari/537.36",
})
def get_auto_quote(self, carrier_url, vehicle_data, driver_data, sitekey):
"""Get auto insurance quote from a single carrier."""
# Step 1: Load quote page
self.session.get(carrier_url)
# Step 2: Submit vehicle info
resp = self.session.post(f"{carrier_url}/vehicle", data=vehicle_data)
# Step 3: Submit driver info
resp = self.session.post(f"{carrier_url}/driver", data=driver_data)
# Step 4: Solve CAPTCHA on quote page
token = solve_recaptcha(sitekey, f"{carrier_url}/quote")
# Step 5: Get quote
resp = self.session.post(f"{carrier_url}/quote", data={
"g-recaptcha-response": token,
})
if resp.status_code == 200:
return self._parse_quote(resp.text)
return None
def compare_carriers(self, carriers, vehicle_data, driver_data):
"""Compare quotes across multiple carriers."""
quotes = []
for carrier in carriers:
try:
quote = self.get_auto_quote(
carrier_url=carrier["url"],
vehicle_data=vehicle_data,
driver_data=driver_data,
sitekey=carrier["sitekey"],
)
quotes.append({
"carrier": carrier["name"],
"status": "success",
"quote": quote,
})
except Exception as e:
quotes.append({
"carrier": carrier["name"],
"status": "failed",
"error": str(e),
})
time.sleep(5) # Delay between carriers
# Sort by price
successful = [q for q in quotes if q["status"] == "success" and q["quote"]]
successful.sort(key=lambda x: x["quote"].get("monthly_premium", float("inf")))
return {
"quotes": quotes,
"best_rate": successful[0] if successful else None,
"total_compared": len(carriers),
"successful": len(successful),
}
def _parse_quote(self, html):
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, "html.parser")
premium_el = soup.select_one(".premium, .monthly-rate, .quote-amount")
coverage_el = soup.select_one(".coverage-summary, .plan-details")
return {
"monthly_premium": premium_el.get_text(strip=True) if premium_el else "",
"coverage": coverage_el.get_text(strip=True) if coverage_el else "",
}
# Usage
collector = InsuranceQuoteCollector(
proxy="http://user-session-abc:pass@residential.proxy.com:5000"
)
vehicle = {
"year": "2022",
"make": "Toyota",
"model": "Camry",
"vin": "",
"mileage": "15000",
}
driver = {
"age": "35",
"gender": "M",
"zip": "90210",
"driving_record": "clean",
}
carriers = [
{"name": "Carrier A", "url": "https://carrier-a.example.com/auto", "sitekey": "6Lc_xxx1"},
{"name": "Carrier B", "url": "https://carrier-b.example.com/auto", "sitekey": "6Lc_xxx2"},
{"name": "Carrier C", "url": "https://carrier-c.example.com/auto", "sitekey": "6Lc_xxx3"},
]
comparison = collector.compare_carriers(carriers, vehicle, driver)
print(f"Best rate: {comparison['best_rate']}")
Perbandingan Paket Asuransi Kesehatan
def compare_health_plans(marketplace_url, demographics, sitekey):
"""Compare health insurance plans on marketplace sites."""
collector = InsuranceQuoteCollector(
proxy="http://user-session-xyz:pass@residential.proxy.com:5000"
)
# Load marketplace
collector.session.get(marketplace_url)
# Submit demographics
collector.session.post(f"{marketplace_url}/demographics", data=demographics)
# Solve CAPTCHA for plan results
token = solve_recaptcha(sitekey, f"{marketplace_url}/plans")
resp = collector.session.post(f"{marketplace_url}/plans", data={
"g-recaptcha-response": token,
})
if resp.status_code == 200:
from bs4 import BeautifulSoup
soup = BeautifulSoup(resp.text, "html.parser")
plans = []
for card in soup.select(".plan-card, .insurance-plan"):
plans.append({
"name": card.select_one(".plan-name").get_text(strip=True) if card.select_one(".plan-name") else "",
"premium": card.select_one(".premium").get_text(strip=True) if card.select_one(".premium") else "",
"deductible": card.select_one(".deductible").get_text(strip=True) if card.select_one(".deductible") else "",
})
return plans
return []
Persyaratan Sesi
Penawaran asuransi selalu multi-step — sticky session sangat diperlukan:
| Langkah | Data yang Dikirim | Persyaratan IP |
|---|---|---|
| 1. Informasi pribadi | Nama, DOB, zip | IP yang sama |
| 2. Kendaraan/properti | Tahun, merek, model | IP yang sama |
| 3. Pemilihan coverage | Limit, deductible | IP yang sama |
| 4. Solve CAPTCHA | Token | IP yang sama |
| 5. Tampilan penawaran | N/A | IP yang sama |
Gunakan sticky session proxy dengan TTL 10–15 menit untuk alur asuransi.
Pemecahan Masalah
| Masalah | Penyebab | Solusi |
|---|---|---|
| Form penawaran reset di tengah alur | IP berubah antar langkah | Gunakan sticky session proxy |
| "Tidak dapat memberikan penawaran" | Validasi data gagal | Periksa field yang wajib diisi |
| CAPTCHA muncul dua kali | Token pertama sudah kedaluarsa | Solve ulang segera |
| Tarif berbeda dari manual | Perbedaan cookie/session | Mulai sesi bersih |
| Rate limiter memblokir request | Terlalu banyak penawaran dari IP | Perlambat, rotate IP antar carrier |
Pertanyaan Umum
Berapa banyak penawaran yang bisa dikumpulkan per hari?
Biasanya 20–50 per carrier per hari dengan delay yang tepat. Melebihi angka ini akan memicu rate limiting dan CAPTCHA yang lebih agresif.
Mengapa perlu sticky session untuk asuransi?
Alur penawaran asuransi bersifat multi-step. Server mengaitkan setiap langkah ke session dan IP Anda. Mengubah IP di tengah alur akan membatalkan session.
Bisakah saya otomatisasi beberapa vertikal asuransi?
Ya. Pendekatan penanganan CAPTCHA yang sama berlaku untuk asuransi mobil, kesehatan, rumah, dan jiwa — hanya field form-nya saja yang berbeda.
Panduan Terkait
- Sticky Session vs Rotating Session
- Persistensi Session Browser
- Metode Autentikasi Proxy