Beban scraping jarang datang rata: ramai beberapa jam, lalu sepi. Membayar server yang menyala 24 jam hanya untuk menyelesaikan CAPTCHA sesekali jelas boros — di sinilah AWS Lambda unggul. Anda menaruh satu fungsi yang memanggil API CaptchaAI, membayar hanya saat kode berjalan, dan Lambda menskalakan dari nol ke ratusan eksekusi bersamaan.
Tutorial ini membangun fungsi penyelesai, mengamankannya dengan Secrets Manager, men-deploy lewat SAM, lalu menambahkan jalur batch SQS. Satu catatan penting: tagihan CaptchaAI dihitung per thread — bukan per solve — jadi konkurensi Lambda dan jumlah thread paket harus diselaraskan.
Kapan Lambda cocok untuk penyelesaian CAPTCHA
Sebelum menulis kode, pastikan Lambda memang model yang tepat untuk beban Anda. Penyelesaian CAPTCHA sebagian besar waktunya habis menunggu jawaban dari API — bukan membebani CPU — jadi fungsi yang murah, cepat menskalakan, dan bebas dari server yang menganggur adalah kombinasi yang pas.
Lambda paling masuk akal ketika:
- Trafik Anda berfluktuasi — misalnya scraping harga atau pemantauan yang ramai pada jam tertentu lalu sepi, sehingga membayar server 24 jam adalah pemborosan.
- Anda ingin penyelesai CAPTCHA menjadi satu endpoint terpisah yang bisa dipanggil banyak layanan lain di belakang API Gateway.
- Volume Anda tumbuh tak terduga dan Anda butuh konkurensi otomatis tanpa mengonfigurasi auto-scaling group.
Sebaliknya, jika Anda menjalankan scraping bervolume tinggi yang konstan sepanjang hari, container di ECS atau satu VM kecil bisa lebih hemat karena Anda tidak membayar per pemanggilan. Untuk pola on-demand dan spiky, Lambda hampir selalu menang.
Fungsi handler Lambda
# lambda_function.py
import json
import os
import time
import urllib.request
import urllib.parse
def lambda_handler(event, context):
"""AWS Lambda handler for CaptchaAI solving."""
api_key = os.environ["CAPTCHAAI_KEY"]
# Parse input
body = json.loads(event.get("body", "{}")) if isinstance(event.get("body"), str) else event
method = body.get("method", "userrecaptcha")
params = body.get("params", {})
try:
token = solve_captcha(api_key, method, params)
return {
"statusCode": 200,
"body": json.dumps({"token": token}),
}
except Exception as e:
return {
"statusCode": 500,
"body": json.dumps({"error": str(e)}),
}
def solve_captcha(api_key, method, params, timeout=90):
"""Solve CAPTCHA using CaptchaAI API."""
# Submit task
submit_data = urllib.parse.urlencode({
"key": api_key,
"method": method,
"json": 1,
**params,
}).encode()
req = urllib.request.Request(
"https://ocr.captchaai.com/in.php",
data=submit_data,
)
with urllib.request.urlopen(req, timeout=30) as resp:
result = json.loads(resp.read())
if result.get("status") != 1:
raise RuntimeError(f"Submit error: {result.get('request')}")
task_id = result["request"]
# Poll for result
start = time.time()
while time.time() - start < timeout:
time.sleep(5)
poll_url = (
f"https://ocr.captchaai.com/res.php"
f"?key={api_key}&action=get&id={task_id}&json=1"
)
with urllib.request.urlopen(poll_url, timeout=15) as resp:
data = json.loads(resp.read())
if data["request"] != "CAPCHA_NOT_READY":
if data.get("status") == 1:
return data["request"]
raise RuntimeError(f"Solve error: {data['request']}")
raise TimeoutError("Solve timeout")
Fungsi solve_captcha di atas mengikuti pola empat langkah yang sama untuk setiap tipe CAPTCHA:
- Kirim task ke
in.phpbesertamethoddan parameter halaman target. - Simpan task ID yang dikembalikan API.
- Polling ke
res.phpsampai statusnya bukanCAPCHA_NOT_READY. - Pakai token terselesaikan pada form atau request yang Anda otomatisasi.
Handler memuat API key dari environment variable dan mengembalikan token dalam respons JSON. Perhatikan bahwa solve_captcha sengaja memakai urllib bawaan Python, bukan requests — dengan begitu Anda tidak perlu membundel dependency tambahan atau mengurus Lambda layer.
Simpan API key di Secrets Manager
import json
import boto3
def get_api_key():
"""Retrieve CaptchaAI key from AWS Secrets Manager."""
client = boto3.client("secretsmanager")
response = client.get_secret_value(SecretId="captchaai/api-key")
secret = json.loads(response["SecretString"])
return secret["api_key"]
Untuk produksi, simpan key di Secrets Manager agar terenkripsi dan bisa dirotasi. Simpan secret-nya:
aws secretsmanager create-secret \
--name captchaai/api-key \
--secret-string '{"api_key":"YOUR_API_KEY"}'
Deploy sebagai kode dengan template SAM
# template.yaml
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Globals:
Function:
Timeout: 120
MemorySize: 256
Runtime: python3.11
Resources:
CaptchaSolverFunction:
Type: AWS::Serverless::Function
Properties:
Handler: lambda_function.lambda_handler
Environment:
Variables:
CAPTCHAAI_KEY: !Sub "{{resolve:secretsmanager:captchaai/api-key:SecretString:api_key}}"
Events:
SolveApi:
Type: Api
Properties:
Path: /solve
Method: post
Policies:
- AWSSecretsManagerGetSecretValuePolicy:
SecretArn: !Sub "arn:aws:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:captchaai/api-key-*"
Outputs:
SolveApiUrl:
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/solve"
Template ini menyatukan fungsi, endpoint API, dan izin baca secret dalam satu berkas.
Build dan deploy fungsi
# Build and deploy
sam build
sam deploy --guided
# Test
curl -X POST https://YOUR_API_ID.execute-api.us-east-1.amazonaws.com/Prod/solve \
-H "Content-Type: application/json" \
-d '{
"method": "userrecaptcha",
"params": {
"googlekey": "SITE_KEY",
"pageurl": "https://example.com"
}
}'
Contoh curl memakai region us-east-1, tetapi tim di Indonesia biasanya deploy ke region terdekat dengan target — ap-southeast-1 (Singapura) atau ap-southeast-3 (Jakarta) — untuk memangkas latensi bolak-balik. Cukup ganti region saat sam deploy --guided; kode fungsi tidak berubah. Perintah sam deploy --guided akan menanyakan nama stack, region, dan konfirmasi perubahan sebelum membuat resource.
Proses batch CAPTCHA dari antrean SQS
Untuk permintaan satu per satu, API Gateway sudah cukup. Tetapi saat Anda harus menyelesaikan ribuan CAPTCHA dalam satu proses — misalnya membersihkan backlog scraping semalam — pola berbasis antrean memberi tiga keuntungan:
- Retry otomatis: task yang gagal kembali ke antrean alih-alih hilang begitu saja.
- Paralelisme: Lambda menarik banyak pesan sekaligus, dibatasi hanya oleh reserved concurrency dan thread paket Anda.
- Peredam lonjakan: antrean menahan kelebihan task sehingga API tidak dibanjiri sekaligus.
Handler SQS berikut memproses setiap pesan dalam batch dan mengembalikan status per task:
import json
import os
import time
import urllib.request
import urllib.parse
def sqs_handler(event, context):
"""Process CAPTCHA tasks from SQS queue."""
api_key = os.environ["CAPTCHAAI_KEY"]
results = []
for record in event["Records"]:
task = json.loads(record["body"])
try:
token = solve_captcha(
api_key,
task["method"],
task["params"],
)
results.append({
"task_id": task.get("id"),
"status": "success",
"token": token[:50],
})
except Exception as e:
results.append({
"task_id": task.get("id"),
"status": "error",
"error": str(e),
})
return {"results": results}
Menyelaraskan konkurensi Lambda dengan thread CaptchaAI
Ini titik yang paling sering terlewat, dan penting terutama bagi tim yang sensitif terhadap biaya. Lambda menskalakan konkurensi hampir tanpa batas, tetapi CaptchaAI menagih per thread bersamaan — bukan per solve. Jika Lambda menjalankan 100 fungsi sekaligus sementara paket Anda hanya menyediakan lebih sedikit thread, sebagian task akan mengantre di sisi CaptchaAI, bukan gagal.
Selaraskan keduanya dengan langkah berikut:
- Perkirakan konkurensi puncak yang benar-benar Anda butuhkan, lalu pilih paket dengan jumlah thread yang sepadan — misalnya PREMIUM ($170/bulan, 100 thread) untuk sekitar 100 penyelesaian bersamaan.
- Batasi reserved concurrency pada fungsi Lambda agar tidak pernah melampaui jumlah thread paket Anda, sehingga tagihan tetap dapat diprediksi.
- Untuk beban batch, biarkan SQS menahan kelebihan task; antrean menyerap lonjakan tanpa Anda perlu menaikkan paket hanya demi puncak sesaat.
Karena harga CaptchaAI datar per thread dengan penyelesaian tak terbatas, model ini cocok untuk tim scraping dan otomatisasi yang volumenya naik-turun — Anda membayar kapasitas, bukan setiap solve.
Batas dan pengaturan Lambda yang perlu diperhatikan
Beberapa angka default Lambda perlu Anda sesuaikan agar cocok dengan karakter beban penyelesaian CAPTCHA yang menunggu jaringan, bukan membebani CPU:
| Faktor | Nilai |
|---|---|
| Batas waktu maksimal | 15 menit (setel ke 2 menit untuk sebagian besar CAPTCHA) |
| Memori | 256 MB sudah cukup (beban ringan, bukan komputasi berat) |
| Konkurensi | Default 1000 eksekusi bersamaan (ajukan kenaikan bila perlu) |
| Cold start | ~500ms untuk Python (dapat diabaikan dibanding waktu penyelesaian) |
| Biaya | ~$0.0001 per penyelesaian (hanya komputasi) |
| Dependency | Pakai urllib (bawaan) agar tidak perlu Lambda layer |
Masalah umum dan solusinya
| Masalah | Penyebab | Solusi |
|---|---|---|
| Fungsi kena timeout | Batas waktu Lambda < waktu penyelesaian | Setel batas waktu ke 120 detik atau lebih |
| Izin ditolak saat baca secret | Kebijakan IAM belum ada | Tambahkan kebijakan baca Secrets Manager |
| Cold start menambah latensi | Pemanggilan jarang | Aktifkan provisioned concurrency |
Error impor untuk requests |
Tidak ikut terbundel di Lambda | Pakai urllib.request (bawaan) atau tambahkan layer |
Pertanyaan yang sering muncul
Region AWS mana yang sebaiknya dipakai dari Indonesia?
Pilih region terdekat dengan situs target. Untuk target regional, ap-southeast-1 (Singapura) atau ap-southeast-3 (Jakarta) biasanya lebih baik daripada region Amerika. API CaptchaAI bisa diakses dari region mana pun; yang menentukan hanya jarak jaringan.
Sebaiknya pakai pemicu API Gateway atau SQS?
Pakai API Gateway saat butuh hasil seketika dalam satu respons HTTP, misalnya di tengah alur login. Pakai SQS untuk batch besar yang asinkron dengan retry bawaan.
Apakah Lambda hemat biaya untuk penyelesaian CAPTCHA?
Ya. Dengan sekitar $0.0001 per pemanggilan, biaya komputasi Lambda dapat diabaikan dibanding biaya API CaptchaAI, dan Anda tidak membayar apa pun saat fungsi menganggur. Yang tetap menentukan total biaya adalah paket thread CaptchaAI Anda, bukan Lambda.
Bisakah satu fungsi Lambda menangani berbagai tipe CAPTCHA?
Bisa. Parameter method yang Anda kirim menentukan tipe yang diproses, jadi fungsi yang sama dapat menangani reCAPTCHA v2/v3, Cloudflare Turnstile, GeeTest v3, hingga CAPTCHA gambar/OCR — cukup ubah method dan parameter halaman target per permintaan tanpa deploy ulang.
Bacaan terkait
- Menjalankan CaptchaAI di Azure Functions
- Alur CAPTCHA event-driven dengan AWS SNS
Mulai serverless — ambil API key CaptchaAI Anda hari ini.