Если API CaptchaAI регулярно присылает неверный текст на изображение CAPTCHA, дело почти никогда не в самом распознавании. В девяти случаях из десяти причина в том, что именно и как вы отправляете на вход: обрезанный скриншот, пережатый PNG, битая base64-строка или недостающая подсказка по языку.
Ниже — таблица частых причин, быстрая самопроверка по симптому и шесть конкретных исправлений с рабочим кодом на Python, которые закрывают почти все подобные тикеты в поддержку.
Причины неправильного ответа
| Причина | Частота | Исправление |
|---|---|---|
| Изображение обрезано неправильно | Очень часто | Захватывайте полный элемент CAPTCHA, а не кусок страницы |
| Низкое разрешение или сильное сжатие | Часто | Отправляйте изображение более высокого качества |
| Неправильная кодировка изображения | Часто | Проверьте кодировку base64 «туда-обратно» |
| Нет подсказки по языку или типу символов | Иногда | Добавьте language или textinstructions |
| Устаревший или просроченный кадр | Иногда | Делайте свежий снимок непосредственно перед решением |
Первые две строки этой таблицы объясняют большинство обращений в поддержку: скрипт снимает скриншот всей формы вместо самого поля CAPTCHA либо сохраняет картинку через конвертер, который режет качество.
Быстрая самопроверка: от симптома к исправлению
Сверьтесь со своим случаем ниже — список отсортирован так же, как исправления дальше по статье, и почти всегда указывает на один конкретный пункт:
- Ответ — бессмысленный набор символов → скорее всего сломана кодировка base64 → см. Исправление 2.
- Ответ близок, но не совпадает → низкое качество или резкость изображения → см. Исправление 3 (предобработка).
- В ответе неверное число символов → не заданы
min_len/max_len→ см. Исправление 4. - В ответе перепутаны буквы и цифры → не задан параметр
numeric→ см. Исправление 4. - Возвращается пустой ответ → пустой или повреждённый файл → см. Исправление 1 (проверка перед отправкой).
- Ответ верный, но форма его не принимает → чувствительность к регистру → добавьте
textinstructions(см. Исправление 4).
Исправление 1. Проверьте качество изображения перед отправкой
Прежде чем разбираться с кодировкой или подсказками, убедитесь, что сам файл вообще пригоден для распознавания: не слишком маленький, не пустой и не «пережат» до артефактов. Простая функция-валидатор ловит большинство проблем ещё до сетевого запроса и экономит поток на заведомо провальных задачах.
import base64
from io import BytesIO
from PIL import Image
def validate_captcha_image(image_path):
"""Check image quality before submitting to CaptchaAI."""
img = Image.open(image_path)
width, height = img.size
issues = []
# Minimum resolution
if width < 50 or height < 20:
issues.append(f"Too small: {width}x{height}px (min 50x20)")
# Check if mostly blank
pixels = list(img.getdata())
if img.mode == "RGB":
white_count = sum(1 for p in pixels if p[0] > 250 and p[1] > 250 and p[2] > 250)
else:
white_count = sum(1 for p in pixels if p > 250)
blank_ratio = white_count / len(pixels)
if blank_ratio > 0.95:
issues.append(f"Image appears blank ({blank_ratio:.0%} white)")
# File size check
img_bytes = BytesIO()
img.save(img_bytes, format="PNG")
size_kb = img_bytes.tell() / 1024
if size_kb < 1:
issues.append(f"File too small ({size_kb:.1f} KB) — may be empty")
if size_kb > 600:
issues.append(f"File too large ({size_kb:.0f} KB) — submit under 600 KB")
return issues
issues = validate_captcha_image("captcha.png")
if issues:
for issue in issues:
print(f"WARNING: {issue}")
else:
print("Image quality OK")
Исправление 2. Кодируйте base64 без потерь
Отдельный класс багов — это не само изображение, а то, что происходит с ним при кодировании: путают путь к файлу и его содержимое, забывают открыть файл в бинарном режиме или обрезают строку при логировании. Проверка «туда-обратно» (encode → decode → сравнить с оригиналом) ловит это за одну строку кода.
import base64
def encode_captcha(image_path):
"""Properly encode a CAPTCHA image to base64."""
with open(image_path, "rb") as f:
raw = f.read()
encoded = base64.b64encode(raw).decode("ascii")
# Verify round-trip
decoded = base64.b64decode(encoded)
assert decoded == raw, "Base64 encoding corrupted the image"
return encoded
# WRONG — encoding a file path string
bad = base64.b64encode(b"captcha.png").decode() # Encodes filename, not image!
# CORRECT — encoding file contents
with open("captcha.png", "rb") as f:
good = base64.b64encode(f.read()).decode()
Исправление 3. Предобработка: масштаб, контраст, резкость
Предобработка нужна не всегда — но если исходный кадр мелкий или блёклый (типично для мобильных скриншотов и сжатых прокси-каналов), апскейл, усиление контраста и резкость перед кодированием заметно повышают шанс на верный ответ.
from PIL import Image, ImageFilter, ImageEnhance
from io import BytesIO
import base64
def preprocess_captcha(image_path):
"""Improve image quality for better OCR accuracy."""
img = Image.open(image_path)
# Convert to RGB if needed
if img.mode != "RGB":
img = img.convert("RGB")
# Upscale small images
width, height = img.size
if width < 200:
scale = 200 / width
img = img.resize(
(int(width * scale), int(height * scale)),
Image.LANCZOS,
)
# Increase contrast
enhancer = ImageEnhance.Contrast(img)
img = enhancer.enhance(1.5)
# Sharpen
img = img.filter(ImageFilter.SHARPEN)
# Convert to PNG bytes
buffer = BytesIO()
img.save(buffer, format="PNG")
return base64.b64encode(buffer.getvalue()).decode()
Исправление 4. Передавайте подсказки по языку и типу символов
Если известны ограничения формата ответа — язык алфавита, только цифры, диапазон длины — их стоит передать явно. Это не обязательный шаг, но он резко сокращает долю ответов «почти верно, но не то»: сервис перестаёт гадать между похожими символами разных алфавитов.
import requests
def solve_image(api_key, image_base64, **hints):
"""Submit image CAPTCHA with quality hints."""
data = {
"key": api_key,
"method": "base64",
"body": image_base64,
"json": 1,
}
# Add optional hints for better accuracy
if "language" in hints:
data["language"] = hints["language"] # 0=default, 1=Cyrillic, 2=Latin
if "textinstructions" in hints:
data["textinstructions"] = hints["textinstructions"]
if "numeric" in hints:
data["numeric"] = hints["numeric"] # 1=digits only, 2=letters only
if "min_len" in hints:
data["min_len"] = hints["min_len"]
if "max_len" in hints:
data["max_len"] = hints["max_len"]
resp = requests.post("https://ocr.captchaai.com/in.php", data=data, timeout=30)
return resp.json()
# Example: Digits-only CAPTCHA, 4-6 characters
result = solve_image(
"YOUR_API_KEY",
encoded_image,
numeric=1,
min_len=4,
max_len=6,
)
# Example: Case-sensitive text
result = solve_image(
"YOUR_API_KEY",
encoded_image,
textinstructions="Case-sensitive, enter exactly as shown",
)
Исправление 5. Снимайте сам элемент CAPTCHA, а не всю страницу
Скриншот всей страницы с последующей ручной обрезкой координатами — источник большинства «съехавших» кадров: после редизайна формы координаты уже не совпадают с полем. Селектор элемента снимает ровно нужную область независимо от вёрстки вокруг.
from selenium import webdriver
from selenium.webdriver.common.by import By
import base64
def capture_captcha_element(driver, selector):
"""Screenshot only the CAPTCHA element, not the full page."""
element = driver.find_element(By.CSS_SELECTOR, selector)
# Element screenshot (better than page crop)
png_bytes = element.screenshot_as_png
# Verify it's not empty
if len(png_bytes) < 500:
raise ValueError("Screenshot too small — element may not be visible")
return base64.b64encode(png_bytes).decode()
# Usage
driver = webdriver.Chrome()
driver.get("https://example.com")
image_b64 = capture_captcha_element(driver, "img#captchaImage")
Для команд, тестирующих формы на CI-раннере в европейском дата-центре (частый выбор для RU-инфраструктуры), тот же принцип работает и в headless-режиме — просто убедитесь, что элемент действительно отрисовался, прежде чем снимать его.
Исправление 6. Свежий кадр для динамических и ротируемых капч
Динамические CAPTCHA перевыпускают изображение через несколько секунд — если между снимком и отправкой прошла пауза (например, скрипт сначала логирует, потом шлёт запрос), CaptchaAI честно распознает уже устаревший кадр, а сайт такой ответ не примет: капча к этому моменту сменилась.
import time
def solve_with_fresh_image(driver, api_key, captcha_selector):
"""Capture and solve CAPTCHA immediately to avoid expiry."""
# Wait for CAPTCHA to load fully
time.sleep(2)
# Capture fresh
element = driver.find_element(By.CSS_SELECTOR, captcha_selector)
png_bytes = element.screenshot_as_png
body = base64.b64encode(png_bytes).decode()
# Submit immediately
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": api_key,
"method": "base64",
"body": body,
"json": 1,
}, timeout=30)
result = resp.json()
if result.get("status") != 1:
raise RuntimeError(result.get("request"))
task_id = result["request"]
# Poll — image CAPTCHAs solve fast
time.sleep(5)
for _ in range(12):
resp = requests.get("https://ocr.captchaai.com/res.php", params={
"key": api_key, "action": "get",
"id": task_id, "json": 1,
}, timeout=15)
data = resp.json()
if data.get("status") == 1:
return data["request"]
if data["request"] != "CAPCHA_NOT_READY":
raise RuntimeError(data["request"])
time.sleep(3)
raise TimeoutError("Image solve timeout")
Частые вопросы
Ниже — вопросы, которые чаще всего задают разработчики после того, как самопроверка выше не дала однозначного ответа.
| Вопрос | Ответ |
|---|---|
Что означает параметр language: 0, 1, 2? |
Это подсказка по алфавиту ожидаемого ответа: 0 — по умолчанию, 1 — кириллица, 2 — латиница. Для форм на русскоязычных сайтах, где текст на картинке кириллический, явная передача language=1 снижает долю ответов, где сервис принял букву за похожую латинскую. |
| Нужно ли предварительно обрабатывать изображение перед отправкой? | Только если исходный кадр низкого качества. Стандартные CAPTCHA-изображения CaptchaAI обрабатывает и без предобработки. Апскейл совсем маленьких картинок и повышение контраста помогают в пограничных случаях — мелкий шрифт, слабый JPEG-артефакт, полупрозрачный фон. |
| Как ограничить длину ответа, если капча всегда из 4–6 символов? | Передайте min_len и max_len в запросе. Это не меняет само распознавание, но отсекает варианты неверной длины и помогает быстрее заметить, что проблема не в длине, а в чём-то другом — например, в кодировке. |
| PNG или JPEG — какой формат лучше для CAPTCHA? | PNG предпочтительнее: он без потерь и не размывает мелкий текст, как это иногда делает агрессивное сжатие JPEG. Если источник — уже готовый JPEG с сайта, не пересжимайте его повторно при перекодировании в base64. |
Можно ли сообщить о неправильном ответе через reportbad? |
Да, используйте конечную точку reportbad с ID задачи. Это не только помогает статистике точности, но и в части случаев возвращает средства на баланс за конкретную ошибочную задачу. |
Похожие материалы
Решайте изображения точно — попробуйте CaptchaAI.