PowerShell — это инструмент автоматизации по умолчанию в Windows. Системные администраторы, инженеры по обеспечению качества и команды DevOps используют его для веб-тестирования, автоматизации форм и мониторинга. Когда эти сценарии попадают в CAPTCHA, HTTP API CaptchaAI интегрируется напрямую через Invoke-RestMethod — никаких модулей для установки не требуется.
В этом руководстве рассматривается решение reCAPTCHA v2/v3, Cloudflare Turnstile и изображений CAPTCHA с помощью готовых к использованию функций и сценариев PowerShell.
Почему PowerShell для автоматизации CAPTCHA
- Встроен в Windows — установка не требуется (PowerShell 5.1+)
- Invoke-RestMethod — встроенная поддержка REST API с автоматическим анализом JSON.
- Планировщик задач — встроенное планирование скриптов, зависящих от CAPTCHA.
- Удобство для трубопроводов — решение цепочки с последующей автоматизацией
- Кроссплатформенность — PowerShell 7+ работает также на Linux и macOS.
Предварительные условия
- PowerShell 5.1 (Windows) или PowerShell 7+ (кроссплатформенный)
- CaptchaAI API-ключ (возьми один здесь)
- Никаких дополнительных модулей не требуется
Основные функции решателя
Отправить задачу
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
}
Результат опроса
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"
}
Решение reCAPTCHA v2
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://https://staging.example.com/qa-login" `
-SiteKey "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-"
Решение Cloudflare Turnstile
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..."
Решение reCAPTCHA v3
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
}
Решение CAPTCHA для изображений
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-адреса
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
}
Полный модуль решателя
Сохранить как CaptchaAI.psm1:
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
Использование модуля
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://https://staging.example.com/qa-login", "SITEKEY")
Write-Host "Token: $($token.Substring(0, 50))..."
Отправка форм с решенными токенами
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://https://staging.example.com/qa-login" `
-SiteKey "SITEKEY"
$result = Submit-FormWithToken `
-Url "https://https://staging.example.com/qa-login" `
-Token $token `
-FormData @{
username = "user@example.com"
password = "password"
}
Write-Host "Response: $($result.StatusCode)"
Параллельное решение с заданиями
$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
Повторить попытку с обработкой ошибок
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"
}
}
}
Интеграция запланированных задач
# Create a scheduled task that runs CAPTCHA automation daily
$action = New-ScheduledTaskAction `
-Execute "powershell.exe" `
-Argument "-ExecutionPolicy RemoteSigned -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"
Поиск неисправностей
| Ошибка | Причина | Исправить |
|---|---|---|
ERROR_WRONG_USER_KEY |
Неверный ключ API | Подтвердите ключ на панели управления |
ERROR_ZERO_BALANCE |
Нет средств | Пополнить счет |
Invoke-RestMethod: SSL/TLS |
Несоответствие версии TLS | Добавить [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 |
The response content cannot be parsed |
Ответ не в формате JSON | Используйте Invoke-WebRequest и анализируйте вручную. |
Ошибка Execution policy |
Скрипт заблокирован | Запустите Set-ExecutionPolicy -Scope CurrentUser RemoteSigned |
Cannot convert to double |
Ошибка анализа баланса | Используйте [double]::Parse($response.request) |
Часто задаваемые вопросы
Работает ли это с PowerShell 5.1 и 7+?
Да. И Invoke-RestMethod, и Invoke-WebRequest работают в PowerShell 5.1 (встроенная в Windows) и PowerShell 7+ (кроссплатформенная).
Нужно ли устанавливать какие-либо модули?
Нет. REST API CaptchaAI работает со встроенными командлетами PowerShell. Никаких внешних модулей не требуется.
Могу ли я использовать это в конвейерах CI/CD?
Да. PowerShell работает в Azure DevOps, GitHub Actions и Jenkins. Сохраните ключ API как секретную переменную.
Как обрабатывать ошибки TLS?
Добавьте [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 вверху вашего скрипта.
Связанные руководства
- Bash/cURL + CaptchaAI Автоматизация оболочки
- Решение CAPTCHA с помощью C#
- CaptchaAI API-документация
Автоматизация CAPTCHA из командной строки Windows —получите свой ключ APIи начните писать скрипты.