Windows otomasyon script'leriniz bir CAPTCHA duvarına takıldığında, çözüm tek bir yerleşik cmdlet kadar yakınınızda: Invoke-RestMethod. CaptchaAI'nin HTTP API'sini PowerShell'e bağlamak için harici modül kurmanıza ya da ekstra bağımlılık eklemenize gerek yok — API anahtarınızı alıp bir POST isteği göndermeniz yeterli.
Bu rehber; reCAPTCHA v2/v3'ü, Cloudflare Turnstile'ı ve resim (OCR) CAPTCHA'larını PowerShell 5.1 ve 7+ üzerinde, doğrudan iş akışınıza kopyalayabileceğiniz üretime hazır fonksiyonlarla nasıl çözeceğinizi adım adım gösterir. Sistem yöneticileri, QA mühendisleri ve DevOps ekipleri için yazıldı.
PowerShell CAPTCHA otomasyonu için neden mantıklı
Ayrı bir çalışma zamanı ya da paket yöneticisi kurmadan, sunucuda zaten hazır olan bir araçla REST çağrısı yapabilmeniz en büyük avantaj. Öne çıkan noktalar:
- Windows'ta yerleşik — kurulum gerektirmez (PowerShell 5.1+)
- Invoke-RestMethod — otomatik JSON ayrıştırmayla yerel REST API desteği
- Görev Zamanlayıcı — CAPTCHA'ya bağımlı script'leri sistem üzerinde zamanlayın
- Boru hattı dostu — çözümü aşağı yönlü otomasyonla zincirleyin
- Platformlar arası — PowerShell 7+ Linux ve macOS'ta da çalışır
Başlamadan önce gerekenler
Kuruluma başlamadan önce elinizde şunların olması yeterli:
- PowerShell 5.1 (Windows) veya PowerShell 7+ (platformlar arası)
- CaptchaAI API anahtarı (buradan edinin)
- Ek modül gerekmez
Temel çözücü fonksiyonları
Tüm çözücüler iki yapı taşına dayanır: görevi gönderen ve sonucu sorgulayan iki fonksiyon. Önce bunları tanımlayın; her CAPTCHA türü için sonra ince birer sarmalayıcı eklersiniz.
Görevi gönderme
Görevi in.php uç noktasına POST eder ve takip için bir task ID döndürür.
function Submit-CaptchaTask {
param(
[Parameter(Mandatory)]
[string]$ApiKey,
[Parameter(Mandatory)]
[hashtable]$TaskParams
)
$body = @{
key = $ApiKey
json = 1
} + $TaskParams
$response = Invoke-RestMethod -Uri "https://ocr.captchaai.com/in.php" `
-Method Post `
-Body $body `
-ContentType "application/x-www-form-urlencoded"
if ($response.status -ne 1) {
throw "Submit failed: $($response.request)"
}
return $response.request
}
Sonucu sorgulama
Task ID'yi res.php üzerinde token hazır olana kadar belirli aralıklarla sorgular.
function Get-CaptchaResult {
param(
[Parameter(Mandatory)]
[string]$ApiKey,
[Parameter(Mandatory)]
[string]$TaskId,
[int]$MaxWaitSeconds = 300,
[int]$PollIntervalSeconds = 5
)
$deadline = (Get-Date).AddSeconds($MaxWaitSeconds)
while ((Get-Date) -lt $deadline) {
Start-Sleep -Seconds $PollIntervalSeconds
$response = Invoke-RestMethod -Uri "https://ocr.captchaai.com/res.php" `
-Method Get `
-Body @{
key = $ApiKey
action = "get"
id = $TaskId
json = 1
}
if ($response.request -eq "CAPCHA_NOT_READY") {
Write-Verbose "Waiting for solution..."
continue
}
if ($response.status -ne 1) {
throw "Solve failed: $($response.request)"
}
return $response.request
}
throw "Timeout: CAPTCHA not solved within $MaxWaitSeconds seconds"
}
Aşağıdaki tüm çözücüler bu ikiliyi çağırır; tür başına yalnızca gönderim parametreleri değişir. Bu yüzden bir kez doğru kurduğunuzda geri kalan her şey ince bir sarmalayıcıdan ibarettir.
reCAPTCHA v2 çözme
reCAPTCHA v2 en sık karşılaşacağınız türdür; çözücü setine buradan başlamak mantıklı.
function Solve-RecaptchaV2 {
param(
[Parameter(Mandatory)]
[string]$ApiKey,
[Parameter(Mandatory)]
[string]$SiteUrl,
[Parameter(Mandatory)]
[string]$SiteKey
)
Write-Host "Submitting reCAPTCHA v2 task..."
$taskId = Submit-CaptchaTask -ApiKey $ApiKey -TaskParams @{
method = "userrecaptcha"
googlekey = $SiteKey
pageurl = $SiteUrl
}
Write-Host "Task ID: $taskId"
Write-Host "Polling for solution..."
$token = Get-CaptchaResult -ApiKey $ApiKey -TaskId $taskId
Write-Host "Solved! Token: $($token.Substring(0, [Math]::Min(50, $token.Length)))..."
return $token
}
# Usage
$apiKey = "YOUR_API_KEY"
$token = Solve-RecaptchaV2 `
-ApiKey $apiKey `
-SiteUrl "https://staging.example.com/qa-login" `
-SiteKey "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-"
googlekey sayfanın reCAPTCHA sitekey'idir; pageurl ise doğrulamanın göründüğü tam adrestir. Dönen token'ı hedef formun g-recaptcha-response alanına yerleştirerek isteği tamamlarsınız.
Cloudflare Turnstile çözme
Turnstile neredeyse aynı akışı kullanır; tek fark method değerinin turnstile olması ve sitekey'in key alanında gönderilmesidir.
function Solve-Turnstile {
param(
[Parameter(Mandatory)]
[string]$ApiKey,
[Parameter(Mandatory)]
[string]$SiteUrl,
[Parameter(Mandatory)]
[string]$SiteKey
)
$taskId = Submit-CaptchaTask -ApiKey $ApiKey -TaskParams @{
method = "turnstile"
key = $SiteKey
pageurl = $SiteUrl
}
return Get-CaptchaResult -ApiKey $ApiKey -TaskId $taskId
}
# Usage
$token = Solve-Turnstile `
-ApiKey "YOUR_API_KEY" `
-SiteUrl "https://example.com/form" `
-SiteKey "0x4AAAAAAAB5..."
Dönen değeri formun cf-turnstile-response alanına yerleştirin — reCAPTCHA'nın g-recaptcha-response alanından farklı olduğuna dikkat edin.
reCAPTCHA v3 çözme
reCAPTCHA v3 görünmezdir ve arka planda bir güven skoru üretir. Gönderim aynı fonksiyonla yapılır; yalnızca sürüm ve eylem adı eklenir.
function Solve-RecaptchaV3 {
param(
[Parameter(Mandatory)]
[string]$ApiKey,
[Parameter(Mandatory)]
[string]$SiteUrl,
[Parameter(Mandatory)]
[string]$SiteKey,
[string]$Action = "verify",
)
$taskId = Submit-CaptchaTask -ApiKey $ApiKey -TaskParams @{
method = "userrecaptcha"
googlekey = $SiteKey
pageurl = $SiteUrl
version = "v3"
action = $Action
}
return Get-CaptchaResult -ApiKey $ApiKey -TaskId $taskId
}
reCAPTCHA v3 aynı gönderim fonksiyonunu kullanır; tek farkı version = "v3" ve sayfada tanımlı action adını eklemenizdir.
Resim (OCR) CAPTCHA çözme
Resim tabanlı CAPTCHA'larda token değil, doğrudan okunmuş metin alırsınız. Görüntüyü base64'e çevirip body alanında gönderin.
function Solve-ImageCaptcha {
param(
[Parameter(Mandatory)]
[string]$ApiKey,
[Parameter(Mandatory)]
[string]$ImagePath
)
if (-not (Test-Path $ImagePath)) {
throw "Image file not found: $ImagePath"
}
$imageBytes = [System.IO.File]::ReadAllBytes($ImagePath)
$base64 = [Convert]::ToBase64String($imageBytes)
$taskId = Submit-CaptchaTask -ApiKey $ApiKey -TaskParams @{
method = "base64"
body = $base64
}
return Get-CaptchaResult -ApiKey $ApiKey -TaskId $taskId
}
# Usage
$text = Solve-ImageCaptcha -ApiKey "YOUR_API_KEY" -ImagePath "C:\captcha.png"
Write-Host "CAPTCHA text: $text"
URL'deki resimden çözme
Görüntü uzak bir adresteyse önce indirip byte dizisini base64'e çevirin.
function Solve-ImageCaptchaFromUrl {
param(
[Parameter(Mandatory)]
[string]$ApiKey,
[Parameter(Mandatory)]
[string]$ImageUrl
)
$imageBytes = (Invoke-WebRequest -Uri $ImageUrl).Content
$base64 = [Convert]::ToBase64String($imageBytes)
$taskId = Submit-CaptchaTask -ApiKey $ApiKey -TaskParams @{
method = "base64"
body = $base64
}
return Get-CaptchaResult -ApiKey $ApiKey -TaskId $taskId
}
Kaynak ne olursa olsun akış aynıdır: kaynak yerel bir dosya (Solve-ImageCaptcha) ya da bir URL (Solve-ImageCaptchaFromUrl) olabilir.
Hazır çözücü modülü
CaptchaAI.psm1 olarak kaydedin:
class CaptchaAISolver {
[string]$ApiKey
[string]$BaseUrl = "https://ocr.captchaai.com"
[int]$PollInterval = 5
[int]$MaxWait = 300
CaptchaAISolver([string]$apiKey) {
$this.ApiKey = $apiKey
}
[string] SolveRecaptchaV2([string]$siteUrl, [string]$siteKey) {
return $this.Solve(@{
method = "userrecaptcha"
googlekey = $siteKey
pageurl = $siteUrl
})
}
[string] SolveTurnstile([string]$siteUrl, [string]$siteKey) {
return $this.Solve(@{
method = "turnstile"
key = $siteKey
pageurl = $siteUrl
})
}
[string] SolveImage([string]$imagePath) {
$bytes = [System.IO.File]::ReadAllBytes($imagePath)
$base64 = [Convert]::ToBase64String($bytes)
return $this.Solve(@{
method = "base64"
body = $base64
})
}
[double] GetBalance() {
$response = Invoke-RestMethod -Uri "$($this.BaseUrl)/res.php" `
-Body @{ key = $this.ApiKey; action = "getbalance"; json = 1 }
return [double]$response.request
}
hidden [string] Solve([hashtable]$params) {
$taskId = $this.Submit($params)
return $this.Poll($taskId)
}
hidden [string] Submit([hashtable]$params) {
$body = @{ key = $this.ApiKey; json = 1 } + $params
$response = Invoke-RestMethod -Uri "$($this.BaseUrl)/in.php" `
-Method Post -Body $body
if ($response.status -ne 1) { throw "Submit: $($response.request)" }
return $response.request
}
hidden [string] Poll([string]$taskId) {
$deadline = (Get-Date).AddSeconds($this.MaxWait)
while ((Get-Date) -lt $deadline) {
Start-Sleep -Seconds $this.PollInterval
$response = Invoke-RestMethod -Uri "$($this.BaseUrl)/res.php" `
-Body @{ key = $this.ApiKey; action = "get"; id = $taskId; json = 1 }
if ($response.request -eq "CAPCHA_NOT_READY") { continue }
if ($response.status -ne 1) { throw "Solve: $($response.request)" }
return $response.request
}
throw "Timeout"
}
}
# Export
Export-ModuleMember
Ayrı fonksiyonlar yerine tekrar kullanılabilir tek bir sınıf isterseniz CaptchaAISolver tüm mantığı toplar: gönderim, sorgulama ve bakiye kontrolü aynı nesnede durur.
Modülü kullanma
using module ile içe aktarın, bir kez örnekleyin ve tüm çağrıları aynı nesne üzerinden yapın:
using module .\CaptchaAI.psm1
$solver = [CaptchaAISolver]::new("YOUR_API_KEY")
# Check balance
$balance = $solver.GetBalance()
Write-Host "Balance: `$$balance"
# Solve reCAPTCHA v2
$token = $solver.SolveRecaptchaV2("https://staging.example.com/qa-login", "SITEKEY")
Write-Host "Token: $($token.Substring(0, 50))..."
Sınıf tabanlı yaklaşım, büyük script'lerde API anahtarını ve yapılandırmayı tek yerde tutarak parametre tekrarını azaltır.
Token'ı forma gönderme
Token'ı almak işin yarısı; asıl doğrulama, onu hedef formla birlikte göndermenizle tamamlanır.
function Submit-FormWithToken {
param(
[string]$Url,
[string]$Token,
[hashtable]$FormData
)
$body = $FormData + @{
"g-recaptcha-response" = $Token
}
$response = Invoke-WebRequest -Uri $Url `
-Method Post `
-Body $body `
-ContentType "application/x-www-form-urlencoded"
return $response
}
# Usage
$token = Solve-RecaptchaV2 -ApiKey "YOUR_API_KEY" `
-SiteUrl "https://staging.example.com/qa-login" `
-SiteKey "SITEKEY"
$result = Submit-FormWithToken `
-Url "https://staging.example.com/qa-login" `
-Token $token `
-FormData @{
username = "user@example.com"
password = "password"
}
Write-Host "Response: $($result.StatusCode)"
Token'ı hedef formun beklediği alanla göndermeniz gerekir: reCAPTCHA için g-recaptcha-response, Turnstile için cf-turnstile-response. Kısa ömürlü olduğundan geciktirmeden gönderin.
Job'larla paralel çözüm
Görevleri tek tek beklemek yerine Start-Job ile eşzamanlı çalıştırıp toplam süreyi belirgin biçimde kısaltabilirsiniz.
$apiKey = "YOUR_API_KEY"
$tasks = @(
@{ Url = "https://site-a.com"; Key = "SITEKEY_A" },
@{ Url = "https://site-b.com"; Key = "SITEKEY_B" },
@{ Url = "https://site-c.com"; Key = "SITEKEY_C" }
)
$jobs = $tasks | ForEach-Object {
$task = $_
Start-Job -ScriptBlock {
param($ApiKey, $Url, $SiteKey)
$taskId = (Invoke-RestMethod -Uri "https://ocr.captchaai.com/in.php" -Method Post -Body @{
key = $ApiKey; json = 1; method = "userrecaptcha"
googlekey = $SiteKey; pageurl = $Url
}).request
$deadline = (Get-Date).AddSeconds(300)
while ((Get-Date) -lt $deadline) {
Start-Sleep -Seconds 5
$result = Invoke-RestMethod -Uri "https://ocr.captchaai.com/res.php" -Body @{
key = $ApiKey; action = "get"; id = $taskId; json = 1
}
if ($result.request -ne "CAPCHA_NOT_READY" -and $result.status -eq 1) {
return @{ Url = $Url; Token = $result.request }
}
}
return @{ Url = $Url; Error = "Timeout" }
} -ArgumentList $apiKey, $task.Url, $task.Key
}
# Wait and collect results
$results = $jobs | Wait-Job | Receive-Job
$results | ForEach-Object {
if ($_.Token) {
Write-Host "$($_.Url): $($_.Token.Substring(0, 50))..."
} else {
Write-Host "$($_.Url): $($_.Error)" -ForegroundColor Red
}
}
$jobs | Remove-Job
Sonuçları toplamadan önce tüm işleri Wait-Job ile bekleyin. Paralel çözümde iki noktaya dikkat edin:
- Eşzamanlı çözüm kapasiteniz planınızdaki thread sayısına bağlıdır.
- Her
Start-Jobayrı bir PowerShell süreci başlatır; çok sayıda iş için bellek kullanımını izleyin.
Yeniden deneme ve hata yönetimi
Geçici ağ ya da kapasite hataları için gönderime yeniden deneme mantığı ekleyin.
function Solve-WithRetry {
param(
[Parameter(Mandatory)]
[string]$ApiKey,
[Parameter(Mandatory)]
[hashtable]$TaskParams,
[int]$MaxRetries = 3
)
$retryableErrors = @(
"ERROR_NO_SLOT_AVAILABLE",
"ERROR_CAPTCHA_UNSOLVABLE"
)
for ($attempt = 0; $attempt -le $MaxRetries; $attempt++) {
if ($attempt -gt 0) {
$delay = [Math]::Pow(2, $attempt) + (Get-Random -Maximum 3)
Write-Host "Retry $attempt/$MaxRetries after $($delay)s..."
Start-Sleep -Seconds $delay
}
try {
$taskId = Submit-CaptchaTask -ApiKey $ApiKey -TaskParams $TaskParams
$result = Get-CaptchaResult -ApiKey $ApiKey -TaskId $taskId
return $result
}
catch {
$errorMsg = $_.Exception.Message
$isRetryable = $retryableErrors | Where-Object { $errorMsg -like "*$_*" }
if (-not $isRetryable -or $attempt -eq $MaxRetries) {
throw
}
Write-Warning "Retryable error: $errorMsg"
}
}
}
Üretimde her istek ilk denemede başarılı olmaz. ERROR_NO_SLOT_AVAILABLE veya ERROR_CAPTCHA_UNSOLVABLE gibi geçici hatalar için üstel geri çekilme (exponential backoff) ile yeniden deneyin; kalıcı hataları ise doğrudan yukarı fırlatın.
Görev Zamanlayıcı ile otomasyon
CAPTCHA'ya bağımlı bir script'i elle çalıştırmak yerine Windows Görev Zamanlayıcı ile planlayın.
# Create a scheduled task that runs CAPTCHA automation daily
$action = New-ScheduledTaskAction `
-Execute "powershell.exe" `
-Argument "-ExecutionPolicy QA tanılama -File C:\Scripts\captcha-automation.ps1"
$trigger = New-ScheduledTaskTrigger -Daily -At "08:00"
Register-ScheduledTask `
-TaskName "CaptchaAutomation" `
-Action $action `
-Trigger $trigger `
-Description "Run daily CAPTCHA automation with CaptchaAI"
Türkiye'deki QA ekipleri için yaygın bir senaryo: bir Windows sunucusunda her gece çalışan checkout akışı smoke testleri. Görev Zamanlayıcı ile bu script'i sabah 08:00'e kurar, gece boyunca CAPTCHA'lı formları otomatik doğrularsınız. Maliyet tarafında CaptchaAI thread bazlı ve USD üzerinden faturalanır — örneğin BASIC ($15/ay, 5 thread) planı, TL kurundaki dalgalanmalardan bağımsız, öngörülebilir aylık bir gider anlamına gelir. Her plan thread başına sınırsız çözüm içerir.
Zamanlanmış görevi kurarken şu iki noktaya dikkat edin:
-Atdeğerini sunucunuzun saat dilimine (Europe/Istanbul) göre ayarlayın.- Görevi çalıştıran hesabın script klasörüne ve ağa erişim yetkisi olduğundan emin olun.
Sorun giderme
En sık karşılaşılan hataların çoğu yanlış anahtar, boş bakiye ya da eski TLS ayarından kaynaklanır:
| Hata | Sebep | Düzeltme |
|---|---|---|
ERROR_WRONG_USER_KEY |
Geçersiz API anahtarı | Anahtarı kontrol panelinde doğrulayın |
ERROR_ZERO_BALANCE |
Bakiye yok | Hesabınıza bakiye yükleyin |
Invoke-RestMethod: SSL/TLS |
TLS sürüm uyuşmazlığı | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12'yi ekleyin |
The response content cannot be parsed |
JSON dışı yanıt | Invoke-WebRequest kullanıp yanıtı elle ayrıştırın |
Execution policy hatası |
Script engellendi | Set-ExecutionPolicy -Scope CurrentUser RemoteSigned'ı çalıştırın |
Cannot convert to double |
Bakiye ayrıştırma hatası | [double]::Parse($response.request)'yi kullanın |
Bir hatayı çözemezseniz önce anahtarınızı ve bakiyenizi panelden doğrulayın; sorunların büyük kısmı bu iki kontrolle kapanır.
Sık sorulan sorular
Aşağıda PowerShell entegrasyonuyla ilgili en sık gelen sorular yer alıyor:
PowerShell 7 ile Linux ve macOS'ta da kullanabilir miyim?
Evet. Invoke-RestMethod ve Invoke-WebRequest çapraz platformdur; buradaki fonksiyonlar Windows'ta PowerShell 5.1 ile, Linux ve macOS'ta ise PowerShell 7+ ile aynı şekilde çalışır. Kod tarafında değişiklik gerekmez.
CaptchaAI hangi CAPTCHA türlerini çözer?
reCAPTCHA v2/v3, Cloudflare Turnstile ve Challenge, GeeTest v3, resim/OCR, grid ve BLS türlerini çözer. hCaptcha ve FunCaptcha (Arkose Labs) desteklenmez; GeeTest v4 çok yakında gelecek. CaptchaFox, Friendly Captcha ve Lemin ise beta aşamasındadır.
API anahtarımı script içinde nasıl güvende tutarım?
Anahtarı koda gömmeyin. Yerelde ortam değişkeni ($env:CAPTCHAAI_KEY) olarak, CI/CD ortamında ise gizli değişken (secret variable) olarak saklayın. Azure DevOps, GitHub Actions ve Jenkins bu yöntemi doğrudan destekler.
Fiyatlandırma thread'e göre mi hesaplanıyor?
Evet. CaptchaAI çözüm başına değil, eşzamanlı thread başına faturalandırılır ve her plan thread başına sınırsız çözüm içerir. BASIC ($15/ay, 5 thread) ile başlar; paralel iş yükünüz arttıkça daha yüksek thread'li planlara geçebilirsiniz.
Bir çözümün zaman aşımına uğraması ne kadar sürer?
Varsayılan olarak Get-CaptchaResult en fazla 300 saniye bekler ve her 5 saniyede bir sorgular. MaxWaitSeconds ve PollIntervalSeconds parametreleriyle bu değerleri iş yükünüze göre ayarlayabilirsiniz.
İlgili rehberler
- Bash/cURL ile CaptchaAI kabuk otomasyonu
- CAPTCHA'ları C# ile çözme
- CaptchaAI API kimlik doğrulama rehberi
CAPTCHA'ları Windows komut satırından otomatikleştirin — API anahtarınızı alın ve script yazmaya başlayın.