Guides

OCR Integration Guide

A practical guide to integrating OCR into your application — handling multi-page PDFs, choosing the right mode, and optimizing for accuracy.

Overview

This guide walks through common OCR integration patterns. For the complete endpoint reference, see the OCR API Reference.

Choosing the Right Mode

Use CaseRecommended ModeWhy
Search indexingsimplePlain text is easier to index; lower cost
Content republishingformattedPreserves tables, headings, and structure
Data extractionformattedStructured output is easier to parse
Quick copy-pastesimpleFastest and cheapest option

Handling Multi-Page PDFs

Each page is returned as a separate object in the pages array. Use the page-level markdown for per-page processing:

for page in data["data"]["pages"]:
    print(f"Page {page['pageNumber']}:")
    print(page["markdown"])
    print("---")

To get the full document as one Markdown string, use the top-level data.markdown field.

Error Handling

Always check success before accessing data. Handle retryable errors with exponential backoff:

import time

def ocr_with_retry(client, payload, max_retries=3):
    for attempt in range(max_retries):
        response = client.post("/api/v1/ocr", json=payload)
        data = response.json()

        if data["success"]:
            return data

        error = data["error"]
        if not error["retryable"]:
            raise Exception(f"Non-retryable error: {error['code']}")

        wait = 2 ** attempt  # 1s, 2s, 4s
        print(f"Retrying in {wait}s... ({error['code']})")
        time.sleep(wait)

    raise Exception("Max retries exceeded")

Using Idempotency Keys

For production workloads, always use idempotency keys to prevent duplicate charges:

import uuid

payload = {
    "image_url": "https://example.com/invoice.pdf",
    "mode": "formatted",
}

response = requests.post(
    "https://image-to-text.org/api/v1/ocr",
    headers={
        "Authorization": "Bearer YOUR_API_KEY",
        "Idempotency-Key": f"ocr-{uuid.uuid4()}",
    },
    json=payload,
)

if response.status_code == 409:
    # Idempotency conflict — the key was reused with different input
    print("Idempotency key conflict — generate a new key and retry")

Processing Large Batches

When processing many files, respect rate limits:

  1. Space requests at least 5 seconds apart
  2. Track daily usage against your plan's limit
  3. Monitor credit balance — check remaining credits before submitting large batches
  4. Use idempotency — protect against accidental double-processing
import time

files = ["doc1.pdf", "doc2.pdf", "doc3.pdf"]
for file_path in files:
    response = requests.post(
        "https://image-to-text.org/api/v1/ocr",
        headers={
            "Authorization": "Bearer YOUR_API_KEY",
            "Idempotency-Key": f"batch-{file_path}-{int(time.time())}",
        },
        files={"file": open(file_path, "rb")},
        data={"mode": "formatted"},
    )

    data = response.json()
    if data["success"]:
        print(f"{file_path}: {data['data']['usage']['credits']} credits")
    else:
        print(f"{file_path}: Error {data['error']['code']}")

    time.sleep(5)  # Respect rate limits

Base64 vs File Upload vs URL

MethodBest ForConsiderations
File uploadLocal files, direct accessSimplest for server-side code
URLFiles already in cloud storageMust be publicly accessible
Base64Generated content, in-memory dataMemory overhead; encode the raw bytes, not a data URI

Accuracy Tips

  • Resolution matters — images below 150 DPI may reduce accuracy
  • Good lighting — well-lit, high-contrast documents work best
  • Straight alignment — rotated text may be harder to detect
  • Clean backgrounds — avoid complex backgrounds behind text
  • Standard fonts — handwritten text has lower accuracy than printed text