Тулси

API распознавания текста

Нужно читать рукопись, чек или накладную прямо из вашей программы? Зарегистрируйтесь — ключ и 40 распознаваний в месяц без карты. Дальше — тариф картой, без писем и созвонков.

Создать аккаунтТарифы APIВиджет на сайтРешения под задачуСтатусOpenAPIPostman

Как вызвать

Один эндпоинт. В заголовке — ключ из кабинета (Authorization: Bearer …).

POST https://toolsie.ru/api/v1/ocr
Authorization: Bearer ВАШ_КЛЮЧ

multipart/form-data:
  file — картинка или PDF
  tool — вид распознавания (см. ниже)

или application/json:
  { "tool": "…", "image_base64": "…", "mime": "image/jpeg", "filename": "doc.jpg" }

Лимиты и форматы

  • Файлы: JPG, PNG, WebP, GIF, PDF. Максимум 8 МБ на запрос.
  • PDF: обрабатываются первые 12 страниц. Если страниц больше — в тексте будет пометка об обрезке.
  • Таймаут: до 60 секунд на запрос (длинные PDF ближе к верхней границе).
  • Частота: до 60 запросов в минуту на ключ. При превышении — HTTP 429 и заголовок Retry-After: 60.
  • Месячный лимит: по тарифу (поле usage и заголовки ниже). Исчерпан — тоже 429 с quota_exceeded.

Что умеет API

Распознавание с фото и PDF. Конвертацию Word→Markdown и обычные картинки через API не отдаём — для этого есть бесплатные страницы на сайте.

  • Рукопись → обычный текстtool=rukopis-v-tekst
  • Почерк врача → текстtool=vrachebny-pocherk
  • Старинная рукопись → текстtool=starinny-tekst
  • Рукопись с формулами → LaTeXtool=rukopis-v-latex
  • Рукописная таблица → таблица для Exceltool=rukopis-v-tablitsu
  • Чек → таблица для Exceltool=chek-v-excel
  • Накладная → таблица для Exceltool=nakladnaya-v-excel
  • Визитка → таблица контактовtool=vizitka-v-excel
  • Любая форма → структурированные данныеtool=form-v-json
  • Фото доски → текстtool=doska-v-tekst
  • Фото таблицы → таблица для Exceltool=foto-tablitsy-v-excel
  • Скриншот интерфейса → HTMLtool=screenshot-v-kod
  • tekst-so-skrinshotatool=tekst-so-skrinshota
  • pokazaniya-schetchikovtool=pokazaniya-schetchikov
  • konspekt-v-markdowntool=konspekt-v-markdown

Что придёт в ответ

Успех — всегда HTTP 200 и поле text. Для табличных инструментов это CSV (строки через \\n), для бланков — JSON внутри строки, для остального — обычный текст.

{
  "text": "распознанный текст или CSV…",
  "tool": "rukopis-v-tekst",
  "usage": {
    "used": 12,
    "quota": 500,
    "remaining": 488,
    "plan": "starter",
    "month": "2026-08"
  }
}

Пример для накладной (CSV в text)

{
  "text": "doc_number,doc_date,supplier,buyer,item,qty,unit,price,line_total\nТН-42,2026-07-01,ООО Поставщик,ИП Иванов,Молоко 1л,10,шт,89.90,899.00",
  "tool": "nakladnaya-v-excel",
  "usage": { "used": 13, "quota": 500, "remaining": 487, "plan": "starter", "month": "2026-08" }
}

Заголовки с остатком лимита

  • X-RateLimit-Limit — месячная квота
  • X-RateLimit-Used — сколько уже потрачено в этом месяце
  • X-RateLimit-Remaining — сколько осталось

При минутном rate limit те же имена означают лимит запросов в минуту (сейчас 60).

Неразборчивый документ

Ошибки из‑за плохого фото обычно нет: API вернёт 200 и черновик. Нечитаемые фрагменты помечаются как [?]. Пустой или почти пустой text значит, что на кадре почти ничего не удалось прочитать — переснимите при нормальном свете. Результат всегда стоит проверить глазами.

Коды ошибок

Тело ответа — JSON с полем error (строковый код).

HTTPerrorЧто делать
401invalid_api_keyПроверьте Bearer-ключ или создайте новый в кабинете
400unknown_toolНеверный tool; в ответе есть allowed
400file_requiredНе передан файл / image_base64
400file_too_largeБольше 8 МБ; в ответе max_bytes
429rate_limitedСлишком часто; ждите Retry-After
429quota_exceededМесячный лимит; смените тариф в кабинете
502ocr_failedСбой распознавания; повторите позже
503ocr_unavailableСервис временно недоступен — см. статус

Примеры на языках

Каждый пример — на своём якоре, можно дать прямую ссылку. Ключ — из кабинета; на фронт его не выносите.

curl

curl -X POST https://toolsie.ru/api/v1/ocr \
  -H "Authorization: Bearer ВАШ_КЛЮЧ" \
  -F "tool=nakladnaya-v-excel" \
  -F "file=@nakladnaya.jpg"

PHP

cURL. Ключ держите в переменной окружения, не в репозитории.

<?php
$key = getenv('TOOLSIE_API_KEY');
$ch = curl_init('https://toolsie.ru/api/v1/ocr');
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer $key"],
  CURLOPT_POSTFIELDS => [
    'tool' => 'nakladnaya-v-excel',
    'file' => new CURLFile('/path/to/nakladnaya.jpg', 'image/jpeg', 'nakladnaya.jpg'),
  ],
]);
$res = curl_exec($ch);
curl_close($ch);
$data = json_decode($res, true);
echo $data['text'] ?? $data['error'] ?? 'empty';

Python

requests. Для табличных tool= поле text — это CSV.

import os
import requests

r = requests.post(
    "https://toolsie.ru/api/v1/ocr",
    headers={"Authorization": f"Bearer {os.environ['TOOLSIE_API_KEY']}"},
    files={"file": open("nakladnaya.jpg", "rb")},
    data={"tool": "nakladnaya-v-excel"},
    timeout=60,
)
r.raise_for_status()
print(r.json()["text"])
print("осталось:", r.headers.get("X-RateLimit-Remaining"))

Node.js

Встроенный fetch (Node 18+) и FormData.

import fs from "node:fs";

const form = new FormData();
form.set("tool", "nakladnaya-v-excel");
form.set("file", new Blob([fs.readFileSync("nakladnaya.jpg")]), "nakladnaya.jpg");

const res = await fetch("https://toolsie.ru/api/v1/ocr", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.TOOLSIE_API_KEY}` },
  body: form,
});
const data = await res.json();
if (!res.ok) throw new Error(data.error || res.statusText);
console.log(data.text);

JavaScript в браузере

Ключ на фронте светить нельзя — проксируйте через свой бэкенд. Ниже — вызов со своего сервера или если ключ только для внутреннего инструмента.

async function recognize(file) {
  const form = new FormData();
  form.set("tool", "chek-v-excel");
  form.set("file", file);

  const res = await fetch("https://toolsie.ru/api/v1/ocr", {
    method: "POST",
    headers: { Authorization: "Bearer ВАШ_КЛЮЧ" },
    body: form,
  });
  const data = await res.json();
  if (!res.ok) throw new Error(data.error || "ocr_failed");
  return data.text;
}

document.querySelector("input[type=file]").addEventListener("change", async (e) => {
  const file = e.target.files?.[0];
  if (file) console.log(await recognize(file));
});

Google Apps Script

Удобно, если учёт живёт в Google Таблицах. Через JSON + base64.

function recognizeDriveFile(fileId) {
  var key = PropertiesService.getScriptProperties().getProperty('TOOLSIE_API_KEY');
  var blob = DriveApp.getFileById(fileId).getBlob();
  var res = UrlFetchApp.fetch('https://toolsie.ru/api/v1/ocr', {
    method: 'post',
    contentType: 'application/json',
    headers: { Authorization: 'Bearer ' + key },
    payload: JSON.stringify({
      tool: 'chek-v-excel',
      mime: blob.getContentType() || 'image/jpeg',
      filename: blob.getName(),
      image_base64: Utilities.base64Encode(blob.getBytes()),
    }),
    muteHttpExceptions: true,
  });
  var data = JSON.parse(res.getContentText());
  return data.text || data.error;
}

Виджет на Тильду, Битрикс, WordPress — инструкции по платформам. Сценарии под учёт и студии — в решениях.

API для распознавания рукописи и документов — Тулси