API de URL a PDF#

El endpoint POST /v1/convert/url-to-pdf convierte cualquier URL de acceso público en un documento PDF de alta fidelidad. Admite renderizado continuo de una sola página o salida paginada con tamaños de página personalizados, además de gestión de carga diferida, cierre de banners de cookies, HTTP Basic Auth, inyección de cookies y encabezados personalizados. Ejecuta las conversiones de forma síncrona para obtener una URL de descarga prefirmada o los bytes del PDF en bruto, o usa el modo asíncrono para convertir varias URLs por lotes con notificaciones por webhook y correo electrónico.


Endpoint#

POST /v1/convert/url-to-pdf

Content-Type: application/json


Autenticación#

Este endpoint admite autenticación tanto con clave privada como con clave pública.

Clave privada#

Incluye tu clave secreta en el encabezado X-API-Key. Usa este método para llamadas servidor a servidor donde la clave nunca se expone al cliente.

X-API-Key: sk_your_private_key

Clave pública con JWT#

Para uso del lado del cliente, primero genera un token JWT con tu clave pública y luego pásalo como token Bearer.

Paso 1 -- Obtén un token:

POST /v1/auth/token
X-API-Key: pk_your_public_key

Paso 2 -- Usa el token:

Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Nota: Las solicitudes con clave pública están restringidas a una sola URL, modo síncrono y descarga directa. El modo asíncrono, el procesamiento por lotes, los webhooks y los correos de notificación no están disponibles con claves públicas.

Parámetros de la solicitud#

Parámetros de nivel superior#

Parámetro Tipo Obligatorio Predeterminado Descripción Restricción de plan
url string or string[] -- Una cadena de URL única o un array de URLs para convertir. Varias URLs requieren el modo asíncrono. --
async_mode boolean No false Ejecuta la conversión de forma asíncrona. Devuelve un batch_id inmediatamente para sondeo (polling). Obligatorio para lotes (varias URLs). Requiere acceso asíncrono
direct_download boolean No false Devuelve los bytes del PDF en bruto en el cuerpo de la respuesta en lugar de una respuesta JSON con una URL prefirmada. Se fuerza a true para claves públicas. Incompatible con async_mode y varias URLs. --
output_format boolean No false Cuando es true con varias URLs, agrupa todos los PDFs de salida en un único archivo ZIP. Requiere varias URLs. Requiere acceso a salida ZIP
output_filename string No Generado automáticamente Nombre de archivo personalizado para el archivo de salida. La extensión .pdf se añade automáticamente. Formato predeterminado: {domain}_{timestamp}.pdf. --
job_id string No -- ID de trabajo proporcionado por el cliente para la recuperación tras timeout. Solo claves públicas. Cuando una conversión síncrona supera los límites de timeout del proxy inverso (60-120s en sitios pesados), el cliente puede sondear GET /v1/convert/status/{job_id} para recuperar el resultado después. Se ignora para claves privadas. --
notification_email string No Correo del propietario del proyecto Dirección de correo a notificar cuando finaliza un trabajo asíncrono. Solo claves privadas. --
callback_url string No -- URL de webhook que recibe una solicitud POST cuando finaliza la conversión. Solo claves privadas. Requiere acceso a webhooks

Parámetros de navegador y renderizado#

Parámetro Tipo Obligatorio Predeterminado Descripción Restricción de plan
viewport_width integer No 1920 Ancho del viewport del navegador en píxeles. --
viewport_height integer No 1080 Alto del viewport del navegador en píxeles. --
single_page boolean No true true renderiza toda la página como una única página continua de PDF. false produce una salida paginada usando el tamaño de página de pdf_options. --
load_media boolean No true Espera a que todas las imágenes y vídeos carguen por completo antes de la conversión. Cuando es false, la conversión es más rápida pero el contenido multimedia puede aparecer como marcador de posición. --
enable_scroll boolean No true Desplaza la página de arriba a abajo para activar el contenido de carga diferida (cargadores basados en IntersectionObserver). --
handle_sticky_header boolean No true Detecta encabezados sticky/fijos y desplaza hacia arriba antes de la captura para que el encabezado se renderice correctamente al inicio del PDF. --
handle_cookies boolean No true Cierra automáticamente los banners de consentimiento de cookies (OneTrust, Cookiebot, Didomi, Usercentrics y banners genéricos). --
wait_for_images boolean No true Espera a que todos los elementos <img> terminen de cargar (timeout de 5 segundos por imagen). --
wait_for_selector string No null Selector CSS que se espera antes de la captura. Devuelve 422 si nunca aparece dentro de wait_for_selector_timeout. Útil para SPAs que hidratan el contenido después de la carga. --
wait_for_selector_timeout integer No 10000 Milisegundos de espera para wait_for_selector (máximo 60000). --
block_ads boolean No false Aborta las solicitudes a dominios conocidos de anuncios/rastreadores para que nunca se carguen, rendericen ni ralenticen la captura. --
block_media boolean No false Aborta por completo las solicitudes de imágenes y audio/vídeo para un renderizado más rápido y ligero. A diferencia de load_media (que solo controla la espera), esto evita por completo que los medios se descarguen. --

Autenticación y solicitudes personalizadas#

Parámetro Tipo Obligatorio Predeterminado Descripción Restricción de plan
auth object No null Credenciales de HTTP Basic Auth para la URL de destino. Formato: {"username": "...", "password": "..."}. No se puede usar junto con un encabezado personalizado Authorization. Requiere acceso a autenticación básica
cookies array No null Array de objetos cookie para inyectar antes de la navegación. Máximo 50 cookies. Cada cookie debe tener name, value y domain o url. Requiere acceso a autenticación básica
headers object No null Diccionario de encabezados HTTP personalizados enviados con cada solicitud a la URL de destino. Máximo 20 encabezados. Encabezados bloqueados: host, content-length, transfer-encoding, connection, upgrade, te, trailer. Requiere acceso a autenticación básica

Opciones de PDF#

Pasa estos parámetros dentro de un objeto pdf_options en el cuerpo de la solicitud.

Parámetro Tipo Predeterminado Descripción
page_size string "A4" Tamaño de página con nombre. Se ignora cuando se establecen tanto page_width como page_height.
page_width float null Ancho de página personalizado en milímetros. Debe ser positivo. page_width y page_height deben establecerse juntos.
page_height float null Alto de página personalizado en milímetros. Debe ser positivo. Ambos deben establecerse juntos.
orientation string "portrait" "portrait" o "landscape". Intercambia ancho y alto cuando se establece en landscape.
margins object {"top": 10, "bottom": 10, "left": 10, "right": 10} Márgenes de página en milímetros. Todos los valores deben ser no negativos.
scale float 1.0 Factor de escala del contenido. Rango: 0.1 a 2.0. Se aplica solo en modo paginado (single_page=false).
grayscale boolean false Convierte el PDF de salida a escala de grises mediante posprocesamiento.
header object null Encabezado de página para el modo paginado. Formato: {"content": "<html>", "height": 15}. Contenido máximo de 2000 caracteres. Altura en mm.
footer object null Pie de página para el modo paginado. Mismo formato que el encabezado.

Tamaños de página admitidos: A0, A1, A2, A3, A4, A5, A6, B0, B1, B2, B3, B4, B5, Letter, Legal, Tabloid, Ledger

Variables de plantilla de encabezado/pie: {{page}}, {{total_pages}}, {{date}}, {{title}}, {{url}}

Nota: Los encabezados y pies de página solo se renderizan en modo paginado (single_page=false). No tienen efecto en el modo continuo de una sola página.

Cada elemento del array cookies debe seguir esta estructura:

Campo Tipo Obligatorio Predeterminado Descripción
name string -- Nombre de la cookie.
value string -- Valor de la cookie.
domain string Condicional -- Dominio de la cookie. Se debe proporcionar domain o url.
url string Condicional -- URL a la que asociar la cookie. Se debe proporcionar domain o url.
path string No "/" Ruta de la cookie. Por defecto es "/" cuando se establece domain.

Respuesta#

Síncrono con descarga directa (direct_download=true)#

Clave privada -- devuelve los bytes del PDF en bruto:

HTTP 200 OK
Content-Type: application/pdf
Content-Disposition: inline; filename="example_20260404_123456789.pdf"
X-Object-Key: env/files/{project_id}/url-to-pdf/example_20260404_123456789.pdf
X-File-Size: 123456
X-Conversion-Time: 12.5
X-Filename: example_20260404_123456789.pdf

(binary PDF data)

Clave pública -- devuelve JSON con una URL prefirmada:

{
    "presigned_url": "https://spaces.example.com/...",
    "object_key": "env/files/{project_id}/url-to-pdf/example_20260404_123456789.pdf",
    "filename": "example_20260404_123456789.pdf",
    "file_size": 123456,
    "conversion_time_seconds": 12.5,
    "job_id": "client-provided-id"
}

Síncrono sin descarga directa (direct_download=false)#

Disponible solo con claves privadas.

{
    "presigned_url": "https://spaces.example.com/...",
    "object_key": "env/files/{project_id}/url-to-pdf/example_20260404_123456789.pdf",
    "filename": "example_20260404_123456789.pdf",
    "file_size": 123456,
    "conversion_time_seconds": 12.5
}

Modo asíncrono#

Devuelve inmediatamente un batch_id para sondeo.

HTTP 202 Accepted
{
    "status": "processing",
    "batch_id": "550e8400-e29b-41d4-a716-446655440000",
    "url_count": 5,
    "output_format": "individual"
}

Cuando output_format=true (agrupación en ZIP):

{
    "status": "processing",
    "batch_id": "550e8400-e29b-41d4-a716-446655440000",
    "url_count": 5,
    "output_format": "zip"
}

Sondeo de estado del trabajo (solo claves públicas)#

El endpoint de sondeo de estado está diseñado para la recuperación de timeout con clave pública. Cuando una conversión síncrona tarda más que el timeout del proxy inverso (típicamente 60s), el cliente puede recuperar el resultado sondeando con el job_id que proporcionó en la solicitud original.

GET /v1/convert/status/{job_id}
Authorization: Bearer <jwt_token>
Estado Respuesta
Procesando {"status": "processing"}
Éxito {"status": "success", "presigned_url": "...", "object_key": "..."}
Fallido {"status": "failed", "error": "..."}

Sondeo de estado del lote (solo claves privadas)#

Para trabajos por lotes asíncronos, sondea el endpoint de estado del lote con el batch_id devuelto en la respuesta 202.

GET /v1/convert/batch/{batch_id}
X-API-Key: sk_your_private_key

Respuesta:

{
    "batch_id": "550e8400-e29b-41d4-a716-446655440000",
    "status": "processing",
    "total": 5,
    "completed": 3,
    "failed": 1,
    "in_progress": 1,
    "output_mode": "individual",
    "zip_download_url": null,
    "items": [
        {
            "source_url": "https://example.com/page1",
            "status": "Success",
            "download_url": "https://spaces.example.com/...",
            "output_file_size": 102400,
            "duration": "2.34"
        },
        {
            "source_url": "https://example.com/page2",
            "status": "Failed",
            "download_url": null,
            "output_file_size": null,
            "duration": "0.87"
        },
        {
            "source_url": "https://example.com/page3",
            "status": "In Progress",
            "download_url": null,
            "output_file_size": null,
            "duration": null
        }
    ]
}

Valores de estado del lote:

Estado Significado
processing Al menos una URL todavía se está convirtiendo
completed Todas las URLs se convirtieron correctamente
partial Todas las URLs terminaron, pero algunas fallaron
failed Todas las URLs fallaron

Cuando output_mode es "zip", se proporciona un único zip_download_url en lugar de valores download_url por elemento.

Payload del webhook callback#

Cuando se proporciona un callback_url, EnConvert envía una solicitud POST a esa URL al finalizar.

Trabajo de una sola URL:

{
    "job_id": "activity_id",
    "status": "success",
    "batch_id": "...",
    "gcs_uri": "object_key",
    "filename": "example_20260404_123456789.pdf",
    "file_size": 123456
}

Trabajo por lotes:

{
    "job_id": "activity_id",
    "status": "success",
    "batch_id": "...",
    "total_tasks": 10,
    "successful_tasks": 8,
    "failed_tasks": 2,
    "tasks": [
        {"url": "https://example.com/page1", "status": "success", "filename": "page1.pdf"},
        {"url": "https://example.com/page2", "status": "failed", "filename": null}
    ]
}

Funcionalidades#

Modo de captura limpia#

EnConvert gestiona automáticamente los obstáculos comunes de las páginas web para producir PDFs limpios:

  • Banners de consentimiento de cookies -- Cierra automáticamente los banners de OneTrust, Cookiebot, Didomi, Usercentrics e implementaciones genéricas. Funciona tanto en la página principal como en los iframes. Usa una estrategia de cerrar primero y aceptar después.
  • Cierre de modales y popups -- Cierra superposiciones usando varias estrategias: tecla Escape, botones de cierre ARIA, botones de cierre basados en clases y botones de diálogo basados en roles.
  • Revelado de animaciones por scroll -- Fuerza la visibilidad de elementos ocultos por bibliotecas de animación activadas por scroll, incluidas WOW.js, AOS, ScrollReveal y GSAP ScrollTrigger.
  • Limpieza de menús desplegables -- Cierra todos los menús desplegables abiertos y convierte los elementos de botón de navegación en enlaces ancla reales para que sigan siendo clicables en el PDF.

Tamaño y dimensiones de página#

  • Modo de una sola página (predeterminado): toda la página web se renderiza como una única página continua de PDF. La altura se calcula dinámicamente a partir del contenido real mediante recorrido del DOM.
  • Modo paginado (single_page=false): la salida usa el page_size, orientation y margins configurados. Admite 18 tamaños con nombre, de A0 a Ledger, o dimensiones personalizadas en milímetros.

HTTP Basic Auth#

Pasa auth con username y password para convertir páginas protegidas con HTTP Basic Authentication. Las credenciales se envían como credenciales HTTP en cada solicitud a la página de destino.

{
    "url": "https://staging.example.com/report",
    "auth": {
        "username": "admin",
        "password": "secret"
    }
}

Inyección de cookies#

Inyecta hasta 50 cookies antes de que se cargue la página. Útil para convertir páginas que requieren una sesión activa o preferencias de usuario específicas.

{
    "url": "https://example.com/dashboard",
    "cookies": [
        {"name": "session_id", "value": "abc123", "domain": "example.com"},
        {"name": "locale", "value": "en-US", "domain": "example.com"}
    ]
}

Encabezados personalizados#

Envía hasta 20 encabezados HTTP personalizados con cada solicitud a la página de destino. Útil para pasar tokens de API, user agents personalizados u otros metadatos de la solicitud.

{
    "url": "https://example.com/report",
    "headers": {
        "X-Custom-Token": "my-token-value",
        "Accept-Language": "en-US"
    }
}

Carga diferida de imágenes#

Cuando load_media y enable_scroll están activados (ambos son true por defecto), el conversor:

  1. Desplaza toda la página lentamente (120px cada 90ms) para activar los cargadores diferidos basados en IntersectionObserver
  2. Espera a que todos los elementos <img> disparen su evento onload (timeout de 5 segundos por imagen)
  3. Espera 500ms para la estabilización del layout después de que carguen todas las imágenes

Establece load_media=false para una conversión más rápida si la fidelidad del contenido multimedia no es crítica -- el conversor usará un desplazamiento rápido (300px cada 30ms) y añadirá estilos de marcador de posición para las imágenes no cargadas.

Gestión de encabezados sticky#

Cuando handle_sticky_header está activado (true por defecto), el conversor detecta elementos con posición fixed y sticky que parecen ser encabezados (usando etiquetas semánticas, roles ARIA y patrones comunes de nombres de clase), y luego desplaza hasta la parte superior de la página antes de la captura para que el encabezado se renderice correctamente al inicio del PDF.

Encabezados y pies de página#

Añade encabezados y pies de página repetidos en modo paginado con contenido HTML y variables de plantilla:

{
    "url": "https://example.com/report",
    "single_page": false,
    "pdf_options": {
        "page_size": "A4",
        "header": {
            "content": "<div style='font-size:10px;text-align:center;width:100%'>Confidential Report</div>",
            "height": 15
        },
        "footer": {
            "content": "<div style='font-size:9px;text-align:center;width:100%'>Page {{page}} of {{total_pages}}</div>",
            "height": 10
        }
    }
}

Salida en escala de grises#

Establece pdf_options.grayscale en true para convertir el PDF final a escala de grises mediante posprocesamiento con Ghostscript.

Funcionalidades adicionales de renderizado#

  • Normalización de unidades de viewport -- Convierte las unidades CSS vh, svh, lvh, dvh a valores fijos en píxeles para evitar problemas de layout en el renderizado de impresión.
  • Modo stealth -- Usa enmascaramiento de huella digital del navegador para evitar la detección de bots en páginas protegidas.
  • Interceptación de popups -- Cierra automáticamente cualquier pestaña o popup nuevo del navegador activado por la página.
  • Bypass de CSP -- Gestiona las restricciones de Content Security Policy y Trusted Types que de otro modo bloquearían la conversión.

Restricciones por plan de suscripción#

Funcionalidad Founding Indie Studio Enterprise
Conversión básica (una URL, síncrona)
pdf_options personalizado
Opciones de viewport y renderizado
Modo asíncrono No
Procesamiento por lotes (varias URLs) No
Agrupación de salida en ZIP No No
Callbacks de webhook No No
HTTP Basic Auth No
Inyección de cookies No
Encabezados personalizados No
Conversiones mensuales 100 Según el plan Según el plan Ilimitado
Límite de tamaño de lote 0 Según el plan Según el plan Ilimitado
Retención de archivos 1 hora Según el plan Según el plan Según el plan

Modo asíncrono#

El modo asíncrono es útil para conversiones de larga duración o al convertir varias URLs.

Cómo funciona#

  1. Envía una solicitud con async_mode=true (o pasa varias URLs, lo que activa el modo asíncrono automáticamente).
  2. La API devuelve HTTP 202 inmediatamente con un batch_id y url_count.
  3. Cada URL se convierte en segundo plano, se sube al almacenamiento y se rastrea individualmente.
  4. Supervisa la finalización mediante notificación por correo o callback de webhook.

Notificación por correo#

Por defecto, se envía un correo de finalización a la dirección de correo del propietario del proyecto cuando termina el trabajo asíncrono. Puedes anular esto con notification_email:

{
    "url": ["https://example.com/page1", "https://example.com/page2"],
    "async_mode": true,
    "notification_email": "[email protected]"
}

Callback de webhook#

Proporciona un callback_url en la solicitud para recibir una notificación POST automática cuando finalice el trabajo:

{
    "url": ["https://example.com/page1", "https://example.com/page2"],
    "async_mode": true,
    "callback_url": "https://your-server.com/webhook/enconvert"
}

El webhook se envía con un timeout de 30 segundos y considera HTTP 200, 201, 202 y 204 como entrega exitosa.


Procesamiento por lotes y en masa#

Convierte varias URLs en una sola solicitud. Requiere modo asíncrono y una clave privada.

Salida individual (predeterminado)#

Cada URL produce un archivo PDF independiente:

{
    "url": [
        "https://example.com/page1",
        "https://example.com/page2",
        "https://example.com/page3"
    ],
    "async_mode": true
}

Salida en paquete ZIP#

Agrupa todos los PDFs en un único archivo ZIP:

{
    "url": [
        "https://example.com/page1",
        "https://example.com/page2",
        "https://example.com/page3"
    ],
    "async_mode": true,
    "output_format": true,
    "output_filename": "monthly-reports"
}

El archivo ZIP se nombra {output_filename}_{timestamp}.zip, o batch_{timestamp}.zip si no se proporciona un nombre personalizado.


Ejemplos de código#

Python (clave privada)#

import requests

response = requests.post(
    "https://api.enconvert.com/v1/convert/url-to-pdf",
    headers={"X-API-Key": "sk_your_private_key"},
    json={
        "url": "https://example.com",
        "single_page": True,
        "pdf_options": {
            "page_size": "A4",
            "margins": {"top": 15, "bottom": 15, "left": 10, "right": 10}
        }
    }
)

data = response.json()
print(data["presigned_url"])

PHP (clave privada)#

$ch = curl_init("https://api.enconvert.com/v1/convert/url-to-pdf");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        "Content-Type: application/json",
        "X-API-Key: sk_your_private_key"
    ],
    CURLOPT_POSTFIELDS => json_encode([
        "url" => "https://example.com",
        "single_page" => true,
        "pdf_options" => [
            "page_size" => "A4",
            "margins" => ["top" => 15, "bottom" => 15, "left" => 10, "right" => 10]
        ]
    ])
]);

$response = curl_exec($ch);
curl_close($ch);

$data = json_decode($response, true);
echo $data["presigned_url"];

Node.js (clave privada)#

const response = await fetch("https://api.enconvert.com/v1/convert/url-to-pdf", {
    method: "POST",
    headers: {
        "Content-Type": "application/json",
        "X-API-Key": "sk_your_private_key"
    },
    body: JSON.stringify({
        url: "https://example.com",
        single_page: true,
        pdf_options: {
            page_size: "A4",
            margins: { top: 15, bottom: 15, left: 10, right: 10 }
        }
    })
});

const data = await response.json();
console.log(data.presigned_url);

Go (clave privada)#

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "net/http"
    "io"
)

func main() {
    body, _ := json.Marshal(map[string]interface{}{
        "url":         "https://example.com",
        "single_page": true,
        "pdf_options": map[string]interface{}{
            "page_size": "A4",
            "margins":   map[string]int{"top": 15, "bottom": 15, "left": 10, "right": 10},
        },
    })

    req, _ := http.NewRequest("POST", "https://api.enconvert.com/v1/convert/url-to-pdf", bytes.NewBuffer(body))
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("X-API-Key", "sk_your_private_key")

    resp, _ := http.DefaultClient.Do(req)
    defer resp.Body.Close()

    respBody, _ := io.ReadAll(resp.Body)
    fmt.Println(string(respBody))
}

JavaScript -- Navegador (clave pública)#

// Step 1: Get a JWT token
const tokenRes = await fetch("https://api.enconvert.com/v1/auth/token", {
    method: "POST",
    headers: { "X-API-Key": "pk_your_public_key" }
});
const { token } = await tokenRes.json();

// Step 2: Convert URL to PDF
const convertRes = await fetch("https://api.enconvert.com/v1/convert/url-to-pdf", {
    method: "POST",
    headers: {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${token}`
    },
    body: JSON.stringify({
        url: "https://example.com"
    })
});

const data = await convertRes.json();
// Open the PDF in a new tab
window.open(data.presigned_url, "_blank");

React (clave pública)#

import { useState } from "react";

function UrlToPdf() {
    const [loading, setLoading] = useState(false);
    const [pdfUrl, setPdfUrl] = useState(null);

    async function convertUrl() {
        setLoading(true);
        try {
            // Get JWT token
            const tokenRes = await fetch("https://api.enconvert.com/v1/auth/token", {
                method: "POST",
                headers: { "X-API-Key": "pk_your_public_key" }
            });
            const { token } = await tokenRes.json();

            // Convert
            const convertRes = await fetch("https://api.enconvert.com/v1/convert/url-to-pdf", {
                method: "POST",
                headers: {
                    "Content-Type": "application/json",
                    "Authorization": `Bearer ${token}`
                },
                body: JSON.stringify({ url: "https://example.com" })
            });

            const data = await convertRes.json();
            setPdfUrl(data.presigned_url);
        } finally {
            setLoading(false);
        }
    }

    return (
        <div>
            <button onClick={convertUrl} disabled={loading}>
                {loading ? "Converting..." : "Convert to PDF"}
            </button>
            {pdfUrl && <a href={pdfUrl} target="_blank" rel="noreferrer">Download PDF</a>}
        </div>
    );
}

export default UrlToPdf;

Respuestas de error#

Estado Condición
400 Bad Request Falta el parámetro url o está vacío
400 Bad Request output_format=true con una sola URL (requiere varias URLs)
400 Bad Request direct_download=true con varias URLs
400 Bad Request direct_download=true con async_mode=true
400 Bad Request Objeto auth inválido (falta username o password)
400 Bad Request cookies inválido (no es un array, supera las 50 entradas, faltan campos obligatorios)
400 Bad Request headers inválido (no es un objeto, supera las 20 entradas, nombres de encabezado bloqueados, valores que no son cadenas)
400 Bad Request Conflicto entre auth y el encabezado personalizado Authorization
400 Bad Request Clave pública intentando usar varias URLs
400 Bad Request pdf_options inválido (tamaño de página no reconocido, escala fuera del rango 0.1-2.0, márgenes negativos, contenido de encabezado/pie que supera los 2000 caracteres)
401 Unauthorized Falta la clave de API / token JWT o es inválido
402 Payment Required Se agotó la cuota mensual de ops
402 Payment Required El lote superaría la cuota mensual de ops restante
402 Payment Required Se alcanzó el límite de almacenamiento
403 Forbidden El endpoint no está entre los endpoints permitidos de la clave de API
403 Forbidden Funcionalidad no disponible en el plan actual (asíncrono, webhook, ZIP, autenticación básica)
403 Forbidden El tamaño del lote supera el límite de lote del plan
404 Not Found ID de trabajo no encontrado (al sondear el estado)
500 Internal Server Error La conversión falló (fallo del navegador, error de renderizado, fallo de posprocesamiento)

Límites#

Límite Valor
Timeout de navegación de página 60 segundos
Timeout de carga por imagen 5 segundos
Timeout de cierre de banner de cookies 3 segundos
Máximo de cookies por solicitud 50
Máximo de encabezados personalizados por solicitud 20
Longitud del contenido de encabezado/pie 2000 caracteres
Rango de escala del PDF 0.1 -- 2.0
Operaciones mensuales Según el plan (Founding: 500)
Tamaño de lote Según el plan (Founding: deshabilitado)
Retención de archivos Según el plan (Founding: 1 hora)
Timeout de entrega de webhook 30 segundos

Preguntas frecuentes#

¿Cómo convierto una página web a PDF con una API REST?#

Envía una solicitud POST a /v1/convert/url-to-pdf con un cuerpo JSON que contenga la url a convertir, autenticándote con tu clave privada en el encabezado X-API-Key (o un token Bearer JWT de una clave pública). La respuesta síncrona devuelve un presigned_url para descargar el PDF, o los bytes del PDF en bruto cuando direct_download=true.

¿Puedo convertir varias URLs a PDF en una sola solicitud de API?#

Sí. Pasa un array de URLs en el parámetro url con async_mode=true (se requiere una clave privada); la API devuelve HTTP 202 con un batch_id que sondeas mediante GET /v1/convert/batch/{batch_id}. Establece output_format=true para agrupar todos los PDFs en un único archivo ZIP.

¿Cómo capturo una página web completa como una única página continua de PDF?#

El modo de una sola página es el predeterminado (single_page=true): toda la página se renderiza como una única página continua de PDF cuya altura se calcula a partir del contenido real. Establece single_page=false para obtener una salida paginada con page_size, orientation, margins y encabezados y pies de página opcionales mediante pdf_options.

¿Por qué mi PDF muestra banners de cookies o imágenes faltantes?#

El cierre de banners de cookies (handle_cookies) y la gestión de carga diferida (enable_scroll, load_media, wait_for_images) son todos true por defecto, y cubren OneTrust, Cookiebot, Didomi, Usercentrics y banners genéricos. Si estableces load_media=false, la conversión es más rápida pero el contenido multimedia puede aparecer como marcador de posición.

¿Puedo convertir a PDF una página protegida por un login?#

Sí. Usa el parámetro auth para HTTP Basic Auth, inyecta hasta 50 cookies de sesión con cookies, o envía hasta 20 encabezados HTTP personalizados con headers. Estas opciones requieren acceso a autenticación básica en tu plan, y auth no se puede combinar con un encabezado personalizado Authorization.