---
seo_title: API de Capturas de Pantalla de Sitios Web | EnConvert
meta_desc: Captura cada página de un sitio con POST /v1/convert/website-to-screenshot. Descubre por sitemap o rastreo completo y agrupa capturas PNG en un ZIP.
keywords: api para capturar pantallazos de un sitio web, capturar todas las páginas de un sitio web con api, screenshot completo de un sitio web api, api de captura de pantalla por sitemap, rastrear y capturar cada página de un sitio web, archivar un sitio web como capturas PNG, automatizar capturas de pantalla de un sitio web, api de captura masiva de páginas
---

# API de Capturas de Pantalla de Sitios Web

El endpoint `POST /v1/convert/website-to-screenshot` descubre cada página de un sitio web (mediante análisis de sitemap o un rastreo completo en anchura), captura una captura de pantalla PNG de página completa de cada página, y agrupa los resultados en un único archivo ZIP. Los trabajos siempre se ejecutan de forma asíncrona: la API devuelve HTTP 202 con un `batch_id` de inmediato, la finalización se señala mediante sondeo del estado del batch, un callback de webhook, o una notificación por correo electrónico, y la respuesta del estado del batch incluye una URL de descarga prefirmada para el ZIP terminado. Requiere un plan de pago y una clave de API privada.

---

## Endpoint

```
POST /v1/convert/website-to-screenshot
```

**Content-Type:** `application/json`

**Formato de salida:** Archivo ZIP que contiene una captura de pantalla PNG por cada página descubierta.

**Modo:** Siempre asíncrono. Devuelve HTTP 202 de inmediato.

---

## Autenticación

Este endpoint requiere una **clave de API privada**. Las claves públicas no son compatibles con la captura de sitios web.

```
X-API-Key: sk_your_private_key
```

---

## Parámetros de la solicitud

### Parámetros de descubrimiento del sitio web

| Parámetro | Tipo | Requerido | Predeterminado | Descripción | Restricción por plan |
|-----------|------|----------|---------|-------------|-------------|
| `url` | `string` | Sí | -- | La URL base del sitio web (p. ej. `https://example.com`). Se usa como raíz para el descubrimiento de páginas. | -- |
| `crawl_mode` | `string` | No | `"auto"` | Método de descubrimiento de URLs. Uno de `"auto"`, `"sitemap"`, o `"full"`. Consulta [Modos de rastreo](#modos-de-rastreo) más abajo. | Sitemap requiere Indie+, Full requiere Studio+ |
| `include_patterns` | `string[]` | No | `null` | Patrones regex para incluir en lista blanca las URLs descubiertas. **Solo se usa en el modo de rastreo `full`.** | -- |
| `exclude_patterns` | `string[]` | No | Valores predeterminados del sistema | Patrones regex para poner en lista negra las URLs. **Solo se usa en el modo de rastreo `full`.** Cuando se omite, usa valores predeterminados integrados que excluyen recursos estáticos, páginas de login/admin/carrito, y paginación profunda. | -- |

### Parámetros de notificación

| Parámetro | Tipo | Requerido | Predeterminado | Descripción | Restricción por plan |
|-----------|------|----------|---------|-------------|-------------|
| `output_filename` | `string` | No | Generado automáticamente | Nombre base personalizado para el archivo ZIP de salida. La marca de tiempo se añade automáticamente. | -- |
| `notification_email` | `string` | No | Correo del propietario del proyecto | Dirección de correo electrónico para notificar cuando el trabajo finalice. | -- |
| `callback_url` | `string` | No | -- | URL de webhook para recibir una solicitud POST al finalizar. | Requiere acceso a webhooks |

### Parámetros del navegador y renderizado

Estos ajustes se aplican a la captura de cada página individual dentro del sitio web.

| Parámetro | Tipo | Requerido | Predeterminado | Descripción | Restricción por plan |
|-----------|------|----------|---------|-------------|-------------|
| `viewport_width` | `integer` | No | `1920` | Ancho del viewport del navegador en píxeles. El ancho de la captura coincide con este valor. | -- |
| `viewport_height` | `integer` | No | `1080` | Alto del viewport del navegador en píxeles. Se usa como referencia para el renderizado y el cálculo de unidades de viewport. | -- |
| `load_media` | `boolean` | No | `true` | Espera a que todas las imágenes y videos terminen de cargar antes de la captura. | -- |
| `enable_scroll` | `boolean` | No | `true` | Desplaza cada página para activar contenido con carga diferida. | -- |
| `handle_sticky_header` | `boolean` | No | `true` | Detecta encabezados fijos (sticky/fixed) y los gestiona antes de la captura. | -- |
| `handle_cookies` | `boolean` | No | `true` | Cierra automáticamente los banners de consentimiento de cookies. | -- |
| `wait_for_images` | `boolean` | No | `true` | Espera a que todos los elementos `<img>` terminen de cargar. | -- |
| `wait_for_selector` | `string` | No | `null` | Selector CSS que se espera antes de la captura, aplicado a cada página. 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 | Requerido | Predeterminado | Descripción | Restricción por plan |
|-----------|------|----------|---------|-------------|-------------|
| `auth` | `object` | No | `null` | Credenciales de HTTP Basic Auth aplicadas a cada página. Formato: `{"username": "...", "password": "..."}`. | Requiere acceso a autenticación básica |
| `cookies` | `array` | No | `null` | Array de objetos de cookies inyectados antes de cada carga de página. Máximo 50 cookies. | Requiere acceso a autenticación básica |
| `headers` | `object` | No | `null` | Encabezados HTTP personalizados enviados con cada solicitud. Máximo 20 encabezados. | Requiere acceso a autenticación básica |

<div class="alert alert-warning">
<strong>No compatible:</strong> Los parámetros <code>single_page</code> y <code>pdf_options</code> no son aplicables a las capturas de pantalla. Cada página siempre se captura como una única imagen PNG de página completa.
</div>

---

## Modos de rastreo

### `"auto"` (predeterminado)

Usa el modo de rastreo más alto que permite tu plan. Si tu plan admite rastreo completo, ejecuta un rastreo completo. Si tu plan solo admite sitemap, ejecuta descubrimiento por sitemap.

### `"sitemap"`

Descubre páginas analizando el `sitemap.xml` del sitio web:

1. Obtiene `{base_url}/sitemap.xml` (tiempo límite de 30 segundos)
2. Si el elemento raíz es `<sitemapindex>`, obtiene recursivamente cada sitemap hijo
3. Extrae todas las entradas `<url><loc>` de los elementos `<urlset>`
4. Devuelve la lista completa de URLs descubiertas

Devuelve un error si falta el sitemap, si devuelve un estado distinto de 200, si contiene XML inválido, o si no tiene URLs.

### `"full"`

Realiza un rastreo exhaustivo en dos fases:

**Fase 1 -- Descubrimiento de semillas:**

1. Analiza `robots.txt` en busca de directivas de sitemap y reglas de rastreo
2. Verifica rutas estándar de sitemap (`/sitemap.xml`, `/wp-sitemap.xml`, `/sitemap_index.xml`, etc.)
3. Descubre feeds RSS/Atom a partir de etiquetas `<link>` y rutas de feed comunes
4. Extrae URLs semilla de todas las fuentes descubiertas

**Fase 2 -- Rastreo de enlaces en anchura:**

1. Comienza desde la URL base más todas las URLs semilla
2. Visita cada página y encola los enlaces del mismo dominio
3. Aplica `include_patterns` y `exclude_patterns` para filtrar enlaces
4. Respeta las reglas de `robots.txt`
5. Detecta y evita trampas de URL infinitas (páginas de calendario, filtros facetados, etc.)
6. Deduplica URLs normalizando el esquema, el host, los parámetros de consulta, y eliminando parámetros de seguimiento (`utm_*`, `fbclid`, `gclid`, etc.)

**Patrones de exclusión predeterminados** (cuando no se proporciona `exclude_patterns`):

- Recursos estáticos: `*.pdf`, `*.zip`, `*.jpg`, `*.png`, `*.gif`, `*.svg`, `*.css`, `*.js`, `*.xml`, `*.json`, `*.mp4`, `*.webm`, `*.woff`, `*.woff2`
- Rutas protegidas: `/login`, `/admin`, `/cart`, `/checkout`
- Paginación profunda: URLs con parámetros `page=` que superan los 3 dígitos

---

## Respuesta

### 202 Accepted (inmediato)

```json
{
    "status": "processing",
    "batch_id": "550e8400-e29b-41d4-a716-446655440000",
    "url_count": 42,
    "total_discovered": 42,
    "discovery_method": "sitemap",
    "output_format": "zip"
}
```

| Campo | Descripción |
|-------|-------------|
| `batch_id` | UUID para hacer seguimiento del trabajo mediante sondeo del estado del batch o webhook. |
| `url_count` | Número de páginas que se capturarán. |
| `total_discovered` | Total de páginas descubiertas por el rastreo. |
| `discovery_method` | `"sitemap"` o `"full_crawl"` según el modo de rastreo efectivo. |

### Sondeo del estado del batch

Consulta con el `batch_id` de la respuesta 202:

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

Devuelve el estado agregado, los estados por URL, y una URL de descarga prefirmada para el ZIP cuando finaliza. Consulta [Sondeo del estado del batch](/es/docs/endpoints/convert/web-pages/url-to-pdf.md#batch-status-polling-private-keys-only) para ver el esquema completo de la respuesta.

### Payload del callback de webhook

Cuando se proporciona `callback_url`, EnConvert envía una solicitud POST al finalizar:

```json
{
    "job_id": "batch-uuid",
    "status": "success",
    "batch_id": "550e8400-e29b-41d4-a716-446655440000",
    "gcs_uri": "env/files/{project_id}/url-to-screenshot/website_20260405_123456789.zip",
    "filename": "website_20260405_123456789.zip",
    "file_size": 12345678,
    "total_tasks": 42,
    "successful_tasks": 40,
    "failed_tasks": 2,
    "tasks": [
        {"url": "https://example.com/", "status": "success", "filename": "example_20260405_001.png"},
        {"url": "https://example.com/about", "status": "success", "filename": "example_20260405_002.png"},
        {"url": "https://example.com/broken", "status": "failed", "error": "Timeout"}
    ]
}
```

### Notificación por correo electrónico

Se envía un correo de finalización a `notification_email` (o al correo del propietario del proyecto por defecto) cuando el trabajo termina, independientemente de si tuvo éxito o falló.

---

## Restricciones por plan de suscripción

| Función | Founding | Indie | Studio | Enterprise |
|---------|------|---------|-----|------------|
| Captura de sitio web | No | Sí | Sí | Sí |
| Modo de rastreo por sitemap | No | Sí | Sí | Sí |
| Modo de rastreo completo | No | No | Sí | Sí |
| Callbacks de webhook | No | No | Sí | Sí |
| HTTP Basic Auth | No | Sí | Sí | Sí |
| Inyección de cookies | No | Sí | Sí | Sí |
| Encabezados personalizados | No | Sí | Sí | Sí |
| Límite de tamaño de batch | 0 | Según el plan | Según el plan | Ilimitado |
| Conversiones mensuales | 100 | Según el plan | Según el plan | Ilimitado |

<div class="alert alert-warning">
<strong>Plan Founding:</strong> La captura de sitios web no está disponible en el plan gratuito. Intentar usar este endpoint devuelve <code>403 Forbidden</code>.
</div>

---

## Ejemplos de código

### Python (clave privada)

```python
import requests
import time

# Start the website capture
response = requests.post(
    "https://api.enconvert.com/v1/convert/website-to-screenshot",
    headers={"X-API-Key": "sk_your_private_key"},
    json={
        "url": "https://example.com",
        "crawl_mode": "sitemap",
        "output_filename": "example-screenshots",
        "viewport_width": 1440,
        "viewport_height": 900
    }
)

data = response.json()
print(f"Batch ID: {data['batch_id']}")
print(f"Pages found: {data['url_count']}")

# Poll for completion
batch_id = data["batch_id"]
while True:
    status = requests.get(
        f"https://api.enconvert.com/v1/convert/batch/{batch_id}",
        headers={"X-API-Key": "sk_your_private_key"}
    ).json()

    print(f"Status: {status['status']} ({status['completed']}/{status['total']})")

    if status["status"] in ("completed", "partial", "failed"):
        if status.get("zip_download_url"):
            print(f"Download: {status['zip_download_url']}")
        break

    time.sleep(5)
```

### PHP (clave privada)

```php
$ch = curl_init("https://api.enconvert.com/v1/convert/website-to-screenshot");
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",
        "crawl_mode" => "sitemap",
        "output_filename" => "example-screenshots",
        "viewport_width" => 1440,
        "viewport_height" => 900
    ])
]);

$response = json_decode(curl_exec($ch), true);
curl_close($ch);

echo "Batch ID: " . $response["batch_id"] . "\n";
echo "Pages found: " . $response["url_count"] . "\n";
```

### Node.js (clave privada)

```javascript
const response = await fetch("https://api.enconvert.com/v1/convert/website-to-screenshot", {
    method: "POST",
    headers: {
        "Content-Type": "application/json",
        "X-API-Key": "sk_your_private_key"
    },
    body: JSON.stringify({
        url: "https://example.com",
        crawl_mode: "sitemap",
        output_filename: "example-screenshots",
        viewport_width: 1440,
        viewport_height: 900
    })
});

const data = await response.json();
console.log(`Batch ID: ${data.batch_id}`);
console.log(`Pages found: ${data.url_count}`);

// Poll for completion
const poll = async () => {
    const status = await fetch(
        `https://api.enconvert.com/v1/convert/batch/${data.batch_id}`,
        { headers: { "X-API-Key": "sk_your_private_key" } }
    ).then(r => r.json());

    console.log(`Status: ${status.status} (${status.completed}/${status.total})`);

    if (["completed", "partial", "failed"].includes(status.status)) {
        if (status.zip_download_url) console.log(`Download: ${status.zip_download_url}`);
        return;
    }
    setTimeout(poll, 5000);
};
poll();
```

### Go (clave privada)

```go
package main

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

func main() {
    body, _ := json.Marshal(map[string]interface{}{
        "url":             "https://example.com",
        "crawl_mode":      "sitemap",
        "output_filename": "example-screenshots",
        "viewport_width":  1440,
        "viewport_height": 900,
    })

    req, _ := http.NewRequest("POST", "https://api.enconvert.com/v1/convert/website-to-screenshot", 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))
}
```

### Con callback de webhook

```json
{
    "url": "https://example.com",
    "crawl_mode": "full",
    "callback_url": "https://your-server.com/webhook/enconvert",
    "output_filename": "example-full-site-screenshots",
    "include_patterns": [".*\\/blog\\/.*", ".*\\/docs\\/.*"]
}
```

### Con autenticación (sitio protegido con contraseña)

```json
{
    "url": "https://staging.example.com",
    "crawl_mode": "sitemap",
    "auth": {
        "username": "admin",
        "password": "staging-password"
    },
    "cookies": [
        {"name": "session_token", "value": "abc123", "domain": "staging.example.com"}
    ]
}
```

---

## Respuestas de error

| Estado | Condición |
|--------|-----------|
| `400 Bad Request` | Falta el parámetro `url` o está vacío |
| `400 Bad Request` | No se encontraron URLs en el sitemap |
| `400 Bad Request` | Tiempo de espera agotado al obtener el sitemap (límite de 30 segundos) |
| `400 Bad Request` | Respuesta distinta de 200 desde la URL del sitemap |
| `400 Bad Request` | XML inválido en el sitemap |
| `400 Bad Request` | Formato de sitemap no reconocido |
| `400 Bad Request` | No se descubrieron páginas (el rastreo completo encontró cero URLs) |
| `400 Bad Request` | Estructura inválida de `auth`, `cookies`, o `headers` |
| `402 Payment Required` | El número de páginas descubiertas supera la cuota mensual de ops |
| `402 Payment Required` | Se alcanzó el límite de almacenamiento |
| `403 Forbidden` | El rastreo de sitios web no está disponible en el plan actual (plan Founding) |
| `403 Forbidden` | El modo de rastreo completo requiere el plan Studio o superior |
| `403 Forbidden` | El número de páginas descubiertas supera el límite de tamaño del batch |
| `403 Forbidden` | Función no disponible en el plan (webhook, autenticación básica) |
| `500 Internal Server Error` | Fallo de rastreo o de captura |

---

## Límites

| Límite | Valor |
|-------|-------|
| Tiempo límite para obtener el sitemap | 30 segundos |
| Tiempo límite global de rastreo (modo full) | 10 minutos |
| Profundidad máxima de rastreo (modo full) | 10 niveles |
| Tiempo límite de rastreo por página (modo full) | 30 segundos |
| Límite de memoria del rastreador | 512 MB |
| Umbral de trampa infinita | 20 URLs por patrón de URL |
| Tiempo límite para obtener robots.txt | 10 segundos |
| Máximo de páginas por rastreo | Límite de tamaño de batch del plan |
| Máximo de cookies por solicitud | 50 |
| Máximo de encabezados personalizados por solicitud | 20 |
| Tiempo límite de entrega de webhook | 30 segundos |
| Conversiones mensuales | Según el plan |
| Retención de archivos | Según el plan |

---

## Preguntas frecuentes

### ¿Cómo capturo cada página de un sitio web con una API?

Envía una solicitud `POST` a `/v1/convert/website-to-screenshot` con la `url` base del sitio y tu clave privada en el encabezado `X-API-Key`. La API descubre cada página (sitemap o rastreo completo), captura un PNG de página completa de cada una, las agrupa en un archivo ZIP, y devuelve HTTP `202` con un `batch_id` que puedes sondear para obtener el enlace de descarga.

### ¿Puedo controlar el tamaño o el formato de las capturas de pantalla?

El ancho de la captura coincide con `viewport_width` (predeterminado `1920`), y `viewport_height` se usa como referencia de renderizado. Cada página siempre se captura como un único PNG de página completa. Los parámetros `single_page` y `pdf_options` no se aplican a las capturas de pantalla.

### ¿Cómo descargo las capturas de pantalla cuando el trabajo finaliza?

Sondea `GET /v1/convert/batch/{batch_id}` con tu clave privada para obtener el estado agregado, los estados por URL, y una URL de descarga prefirmada del ZIP, o pasa un `callback_url` para recibir un POST de webhook al finalizar. También se envía un correo de finalización a `notification_email` (o al propietario del proyecto por defecto).

### ¿Puedo capturar un sitio protegido con contraseña o en staging?

Sí, en planes con acceso a autenticación básica: pasa `auth` con `username` y `password` para aplicar HTTP Basic Auth a cada página, inyecta hasta 50 `cookies` de sesión, o envía hasta 20 `headers` personalizados.

### ¿Por qué el endpoint de captura de pantalla de sitios web devuelve 403 Forbidden?

Las causas más comunes: la captura de sitios web no está disponible en el plan Founding, `crawl_mode: "full"` requiere Studio o superior, el número de páginas descubiertas supera el límite de tamaño de batch de tu plan, o una función solicitada (webhook, autenticación básica) no está incluida en tu plan.
