Ejecuta Tesseract como API
o servicio autoalojado.
Envuelve Tesseract en un servicio HTTP con confianza: un endpoint FastAPI de producción, concurrencia con pool de procesos, una imagen Docker con paquetes de idioma y comprobaciones de estado, escalado y contrapresión, y despliegue serverless, con los compromisos de privacidad y coste frente a las API OCR gestionadas.
TL;DR — un servicio mínimo
Envuelve la CLI o el enlace pytesseract detrás de HTTP. La imagen nunca sale de tu infraestructura.
pip install fastapi uvicorn python-multipart pytesseract pillow
# instala primero el motor + los paquetes de idioma (ver la guía de instalación)
uvicorn app:app --host 0.0.0.0 --port 8000Luego llámalo: curl -F "file=@factura.png" "http://localhost:8000/ocr?lang=spa". Tesseract se instala según la guía de instalación.
Primero, las decisiones de diseño
Tres elecciones definen todo el servicio.
| Decisión | Opciones | Guía |
|---|---|---|
| Síncrono vs asíncrono | Petición bloqueante vs cola de trabajos | Síncrono para imágenes individuales de pocos segundos; IDs de trabajo asíncronos para documentos grandes o por lotes. |
| Entrada | Subida multipart vs JSON base64 | Prefiere multipart para imágenes binarias; base64 solo cuando el cliente no puede subir archivos (añade ~33% de tamaño). |
| Salida | Texto plano, JSON, hOCR/ALTO, PDF con búsqueda | Devuelve JSON por defecto; ofrece hOCR para el diseño y una URL de descarga de PDF para archivos. |
Una intención principal por endpoint. Mantén /ocr devolviendo texto y añade endpoints separados para PDFs y datos de diseño en lugar de sobrecargar una respuesta.
Un servicio Python de producción (FastAPI)
Validación, límites de tamaño, un tiempo de espera y OCR fuera del bucle de eventos.
import asyncio, io
from concurrent.futures import ProcessPoolExecutor
from fastapi import FastAPI, File, UploadFile, HTTPException, Query
from PIL import Image
import pytesseract
app = FastAPI(title="Tesseract OCR API")
pool = ProcessPoolExecutor(max_workers=4)
MAX_BYTES = 10 * 1024 * 1024 # 10 MB
LANGS = {"eng", "deu", "fra", "spa"}
def _ocr(data: bytes, lang: str) -> str:
image = Image.open(io.BytesIO(data))
return pytesseract.image_to_string(image, lang=lang)
@app.get("/health")
def health():
return {"status": "ok"}
@app.post("/ocr")
async def ocr(file: UploadFile = File(...), lang: str = Query("spa")):
if lang not in LANGS:
raise HTTPException(400, "Idioma no soportado")
data = await file.read()
if len(data) > MAX_BYTES:
raise HTTPException(413, "Archivo demasiado grande")
loop = asyncio.get_running_loop()
try:
text = await asyncio.wait_for(loop.run_in_executor(pool, _ocr, data, lang), timeout=30)
except asyncio.TimeoutError:
raise HTTPException(504, "El OCR agotó el tiempo")
return {"text": text, "lang": lang}Detalles clave: lista blanca de idiomas, aplica un límite de bytes antes de decodificar, ejecuta el OCR en un pool de procesos y limita el tiempo de reloj. Consulta la guía de Python para la API completa de pytesseract.
Contenerízalo
Incluye Tesseract y los paquetes de idioma en la imagen para que las réplicas sean idénticas.
FROM python:3.12-slim
RUN apt-get update && apt-get install -y --no-install-recommends \
tesseract-ocr tesseract-ocr-eng tesseract-ocr-spa \
libgl1 libglib2.0-0 && rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
EXPOSE 8000
HEALTHCHECK CMD python -c "import urllib.request;urllib.request.urlopen('http://localhost:8000/health')"
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "2"]Añade solo los paquetes de idioma que necesites para mantener la imagen pequeña. La guía de instalación cubre Docker y la ubicación de tessdata con más detalle.
Concurrencia y escalado
El OCR es intensivo en CPU: paraleliza con procesos, no con hilos.
- Pool de procesos o subprocesos de la CLI: el GIL de Python hace que un pool de hilos no acelere el OCR. Usa
ProcessPoolExecutoro un pool de subprocesos detesseract. - Workers vs réplicas: ejecuta unos pocos workers de uvicorn por contenedor y escala réplicas horizontalmente tras un balanceador.
- Colas: para ráfagas o documentos largos, acepta la subida, devuelve un ID de trabajo y procesa desde una cola (Celery, RQ o un bróker).
- Contrapresión: limita la cola y rechaza con
429cuando esté saturada en lugar de dejar que la latencia se dispare. - Límites de recursos: fija CPU/memoria por worker y establece un tiempo de espera de OCR para que una imagen mala no bloquee una réplica.
Seguridad y privacidad
El autoalojamiento es la razón principal por la que los equipos eligen Tesseract.
- Sin salida de datos: las imágenes permanecen dentro de tu red, importante para documentos legales, médicos y financieros.
- Valida la entrada: comprueba el tipo MIME y los bytes mágicos, no solo la extensión; decodifica en un try/except.
- Limita los recursos: tamaño máximo de subida, tiempo de espera por petición y un techo de memoria para resistir bombas de descompresión.
- Autentica: pon una clave de API o una puerta de enlace delante; los endpoints de OCR son caros de abusar.
- Elimina metadatos: si persistes archivos, quita el EXIF y borra los originales según un calendario.
Plataformas serverless y de contenedores
- Runtimes de contenedores: Cloud Run, imágenes de contenedor de AWS Lambda y Fly.io ejecutan una imagen de Tesseract sin gestionar servidores.
- Arranques en frío: una imagen de Tesseract con paquetes de idioma es grande, así que los arranques en frío son lentos; mantén una instancia caliente para tráfico sensible a la latencia.
- Límites: sube la memoria y el tiempo de espera; un tiempo de espera predeterminado pequeño matará documentos grandes.
- Disco efímero: escribe archivos temporales solo en
/tmp; trata el sistema de archivos como desechable.
Tesseract autoalojado vs API OCR gestionadas
| Dimensión | Tesseract autoalojado | API OCR gestionada |
|---|---|---|
| Coste | Infraestructura fija; sin tarifa por página | Pago por petición/página; escala con el volumen |
| Privacidad | Los documentos nunca salen de tu red | Los documentos se envían a un tercero |
| Precisión | Sólido en impresión limpia; ajustable por dominio | A menudo más fuerte en escaneos difíciles y escritura a mano |
| Control | Total: versiones, idiomas, modelos personalizados | Hoja de ruta y cuotas del proveedor |
| Operaciones | Tú lo ejecutas: escalado, actualizaciones, monitorización | Totalmente gestionado |
Muchos equipos autoalojan Tesseract para trabajos de gran volumen y sensibles a la privacidad y recurren a una API gestionada solo para la minoría difícil de documentos.
Preguntas frecuentes sobre la API
¿Cómo ejecuto Tesseract OCR como API?
Envuelve la CLI o pytesseract en FastAPI/Flask, expón POST /ocr y contenerízalo. Las imágenes permanecen en tu infraestructura.
¿Hilos o procesos?
Procesos. El OCR es intensivo en CPU y el GIL bloquea el paralelismo de hilos; usa ProcessPoolExecutor o subprocesos de la CLI.
¿Es privada una API autoalojada?
Sí: las imágenes subidas se procesan localmente y nunca se envían a terceros, a diferencia de las API OCR gestionadas.
¿Puede ejecutarse serverless?
Sí, en plataformas de contenedores como Cloud Run, imágenes de contenedor de Lambda o Fly.io; cuida los arranques en frío y el tamaño de la imagen con paquetes de idioma.
¿Qué formatos puedo devolver?
Texto plano, JSON con confianza, hOCR/ALTO o un PDF con búsqueda mediante una URL de descarga.