# Raspado en lote (/es/features/batch-scrape)

<!-- agent-signals: reading_time_min: 8 · est_tokens: 3981 · updated: 2026-07-30 -->
Related: [Búsqueda](/es/features/search.md), [Highlights de búsqueda](/es/features/search-highlights.md), [Índice de investigación](/es/features/research.md), [scraping](/es/features/scrape.md), [Scraping más rápido](/es/features/fast-scraping.md), [Modo JSON - Resultado estructurado](/es/features/llm-extract.md)

El raspado en lote permite raspar múltiples URL en un solo trabajo. Pasa una lista de URL y parámetros opcionales, y Firecrawl las procesa de forma concurrente y devuelve todos los resultados de una sola vez.

* Funciona como `/crawl` pero para una lista explícita de URL
* Modos síncrono y asíncrono
* Compatible con todas las opciones de raspado, incluida la extracción estructurada
* Concurrencia configurable por trabajo

<div id="operations">
  ## Operaciones [#operaciones]
</div>

| Tarea                                | Referencia de la API                                                            | Vocabulario del SDK                                                       |
| ------------------------------------ | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| Iniciar un lote                      | [`batch-scrape`](/es/api-reference/endpoint/batch-scrape)                       | `batchScrape` / `batch_scrape`, `startBatchScrape` / `start_batch_scrape` |
| Consultar el estado y los resultados | [`batch-scrape-get`](/es/api-reference/endpoint/batch-scrape-get)               | `getBatchScrapeStatus` / `get_batch_scrape_status`                        |
| Cancelar un lote en ejecución        | [`batch-scrape-delete`](/es/api-reference/endpoint/batch-scrape-delete)         | Cancelar o eliminar el trabajo del lote por ID                            |
| Revisar errores                      | [`batch-scrape-get-errors`](/es/api-reference/endpoint/batch-scrape-get-errors) | Helper de error/estado para URL fallidas                                  |

<div id="how-it-works">
  ## Cómo funciona [#cómo-funciona]
</div>

Puedes ejecutar un scrape por lotes de dos maneras:

| Modo      | Método del SDK (JS / Python)              | Comportamiento                                                           |
| --------- | ----------------------------------------- | ------------------------------------------------------------------------ |
| Síncrono  | `batchScrape` / `batch_scrape`            | Inicia el lote y espera a que finalice, devolviendo todos los resultados |
| Asíncrono | `startBatchScrape` / `start_batch_scrape` | Inicia el lote y devuelve un ID de trabajo para polling o webhooks       |

<div id="basic-usage">
  ## Uso básico [#uso-básico]
</div>

<CodeGroup>
  <CodeBlockTabs defaultValue="Python" groupId="curl+node+python">
    <CodeBlockTabsList>
      <CodeBlockTabsTrigger value="Python">
        Python
      </CodeBlockTabsTrigger>

      <CodeBlockTabsTrigger value="Node">
        Node
      </CodeBlockTabsTrigger>

      <CodeBlockTabsTrigger value="cURL">
        cURL
      </CodeBlockTabsTrigger>
    </CodeBlockTabsList>

    <CodeBlockTab value="Python">
      ```python  
      from firecrawl import Firecrawl

      firecrawl = Firecrawl(api_key="fc-YOUR-API-KEY")

      # Asíncrono: inicia el lote y devuelve un ID de trabajo inmediatamente
      start = firecrawl.start_batch_scrape([
          "https://firecrawl.dev",
          "https://docs.firecrawl.dev",
      ], formats=["markdown"])

      status = firecrawl.get_batch_scrape_status(start.id)

      # O síncrono: inicia el lote y espera a que finalice
      job = firecrawl.batch_scrape([
          "https://firecrawl.dev",
          "https://docs.firecrawl.dev",
      ], formats=["markdown"], poll_interval=2, wait_timeout=120)

      print(job.status, job.completed, job.total)
      ```
    </CodeBlockTab>

    <CodeBlockTab value="Node">
      ```js  
      import { Firecrawl } from 'firecrawl';

      const firecrawl = new Firecrawl({ apiKey: "fc-YOUR-API-KEY" });

      // Asíncrono: inicia el lote y devuelve un ID de trabajo inmediatamente
      const { id } = await firecrawl.startBatchScrape([
        'https://firecrawl.dev',
        'https://docs.firecrawl.dev'
      ], {
        options: { formats: ['markdown'] },
      });

      const status = await firecrawl.getBatchScrapeStatus(id);

      // O síncrono: inicia el lote y espera a que finalice
      const job = await firecrawl.batchScrape([
        'https://firecrawl.dev',
        'https://docs.firecrawl.dev'
      ], { options: { formats: ['markdown'] }, pollInterval: 2, timeout: 120 });

      console.log(job.status, job.completed, job.total);
      ```
    </CodeBlockTab>

    <CodeBlockTab value="cURL">
      ```bash  
      curl -s -X POST "https://api.firecrawl.dev/v2/batch/scrape" \
        -H "Authorization: Bearer $FIRECRAWL_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{
          "urls": ["https://firecrawl.dev", "https://docs.firecrawl.dev"],
          "formatos": ["markdown"]
        }'
      ```
    </CodeBlockTab>
  </CodeBlockTabs>
</CodeGroup>

<div id="response">
  ### Respuesta [#respuesta]
</div>

Invocar `batchScrape` / `batch_scrape` devuelve los resultados completos cuando el lote finaliza.

```json title="Completado"
{
  "status": "completed",
  "total": 36,
  "completed": 36,
  "creditsUsed": 36,
  "expiresAt": "2024-00-00T00:00:00.000Z",
  "next": "https://api.firecrawl.dev/v2/batch/scrape/123-456-789?skip=26",
  "data": [
    {
      "markdown": "[Página principal de la documentación de Firecrawl![logotipo claro](https://mintlify.s3-us-west-1.amazonaws.com/firecrawl/logo/light.svg)!...",
      "html": "<!DOCTYPE html><html lang=\"en\" class=\"js-focus-visible lg:[--scroll-mt:9.5rem]\" data-js-focus-visible=\"\">...",
      "metadata": {
        "title": "Crea un «chat con el sitio web» usando Groq Llama 3 | Firecrawl",
        "language": "en",
        "sourceURL": "https://docs.firecrawl.dev/learn/rag-llama3",
        "description": "Aprende a usar Firecrawl, Groq Llama 3 y LangChain para crear un bot de «chat con tu sitio web»."
        "ogLocaleAlternate": [],
        "statusCode": 200
      }
    },
    ...
  ]
}
```

Invocar `startBatchScrape` / `start_batch_scrape` devuelve un ID de tarea que puedes monitorear mediante `getBatchScrapeStatus` / `get_batch_scrape_status`, el endpoint de la API `/batch/scrape/{id}` o webhooks. Los resultados de la tarea están disponibles a través de la API durante 24 horas después de su finalización. Después de este período, aún puedes ver el historial y los resultados de tus ejecuciones de batch scrape en los [activity logs](https://www.firecrawl.dev/app/logs).

```json
{
  "success": true,
  "id": "123-456-789",
  "url": "https://api.firecrawl.dev/v2/batch/scrape/123-456-789"
}
```

<div id="concurrency">
  ## Concurrencia [#concurrencia]
</div>

De forma predeterminada, un trabajo de extracción por lotes usa todo el límite de navegadores concurrentes de tu equipo (consulta [Rate Limits](/es/rate-limits)). Puedes reducir este valor por trabajo con el parámetro `maxConcurrency`.

Por ejemplo, `maxConcurrency: 50` limita ese trabajo a 50 extracciones simultáneas. Establecer este valor demasiado bajo en lotes grandes ralentizará significativamente el procesamiento, así que solo redúcelo si necesitas dejar capacidad para otros trabajos concurrentes.

<div id="structured-extraction">
  ## Extracción estructurada [#extracción-estructurada]
</div>

Puedes usar el raspado por lotes para extraer datos estructurados de cada página del lote. Esto es útil si quieres aplicar el mismo esquema a una lista de URL.

<CodeGroup>
  <CodeBlockTabs defaultValue="Python" groupId="curl+node+python">
    <CodeBlockTabsList>
      <CodeBlockTabsTrigger value="Python">
        Python
      </CodeBlockTabsTrigger>

      <CodeBlockTabsTrigger value="Node">
        Node
      </CodeBlockTabsTrigger>

      <CodeBlockTabsTrigger value="cURL">
        cURL
      </CodeBlockTabsTrigger>
    </CodeBlockTabsList>

    <CodeBlockTab value="Python">
      ```python  
      from firecrawl import Firecrawl

      firecrawl = Firecrawl(api_key="fc-YOUR_API_KEY")

      # Extrae varios sitios web:
      batch_scrape_result = firecrawl.batch_scrape(
          ['https://docs.firecrawl.dev', 'https://docs.firecrawl.dev/sdks/overview'], 
          formats=[{
              'type': 'json',
              'prompt': 'Extrae el título y la descripción de la página.',
              'schema': {
                  'type': 'object',
                  'properties': {
                      'title': {'type': 'string'},
                      'description': {'type': 'string'}
                  },
                  'required': ['title', 'description']
              }
          }]
      )
      print(batch_scrape_result)

      # O puedes usar el método start:
      batch_scrape_job = firecrawl.start_batch_scrape(
          ['https://docs.firecrawl.dev', 'https://docs.firecrawl.dev/sdks/overview'], 
          formats=[{
              'type': 'json',
              'prompt': 'Extrae el título y la descripción de la página.',
              'schema': {
                  'type': 'object',
                  'properties': {
                      'title': {'type': 'string'},
                      'description': {'type': 'string'}
                  },
                  'required': ['title', 'description']
              }
          }]
      )
      print(batch_scrape_job)

      # Luego puedes usar el ID del job para comprobar el estado de la extracción por lotes:
      batch_scrape_status = firecrawl.get_batch_scrape_status(batch_scrape_job.id)
      print(batch_scrape_status)
      ```
    </CodeBlockTab>

    <CodeBlockTab value="Node">
      ```js  
      import { Firecrawl, ScrapeResponse } from 'firecrawl';

      const firecrawl = new Firecrawl({apiKey: "fc-YOUR_API_KEY"});

      // Define el esquema para extraer el contenido
      const schema = {
        type: "object",
        properties: {
          title: { type: "string" },
          description: { type: "string" }
        },
        required: ["title", "description"]
      };

      // Extrae varias webs (sincrónico):
      const batchScrapeResult = await firecrawl.batchScrape(['https://docs.firecrawl.dev', 'https://docs.firecrawl.dev/sdks/overview'], { 
        formats: [
          {
            type: "json",
            prompt: "Extract the title and description from the page.",
            schema: schema
          }
        ]
      });

      // Muestra todos los resultados del scraping por lotes:
      console.log(batchScrapeResult)

      // O puedes usar el método start:
      const batchScrapeJob = await firecrawl.startBatchScrape(['https://docs.firecrawl.dev', 'https://docs.firecrawl.dev/sdks/overview'], { 
        formats: [
          {
            type: "json",
            prompt: "Extract the title and description from the page.",
            schema: schema
          }
        ]
      });
      console.log(batchScrapeJob)

      // Luego puedes usar el ID del trabajo para comprobar el estado del scraping por lotes:
      const batchScrapeStatus = await firecrawl.getBatchScrapeStatus(batchScrapeJob.id);
      console.log(batchScrapeStatus)
      ```
    </CodeBlockTab>

    <CodeBlockTab value="cURL">
      ```bash  
      curl -X POST https://api.firecrawl.dev/v2/batch/scrape \
          -H 'Content-Type: application/json' \
          -H 'Authorization: Bearer TU_CLAVE_DE_API' \
          -d '{
            "urls": ["https://docs.firecrawl.dev", "https://docs.firecrawl.dev/sdks/overview"],
            "formats" : [{
              "type": "json",
              "prompt": "Extrae el título y la descripción de la página.",
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  }
                },
                "required": [
                  "title",
                  "description"
                ]
              }
            }]
          }'
      ```
    </CodeBlockTab>
  </CodeBlockTabs>
</CodeGroup>

<div id="response">
  ### Respuesta [#respuesta-1]
</div>

`batchScrape` / `batch_scrape` devuelve resultados completos:

```json title="Completado"
{
  "status": "completed",
  "total": 36,
  "completed": 36,
  "creditsUsed": 36,
  "expiresAt": "2024-00-00T00:00:00.000Z",
  "next": "https://api.firecrawl.dev/v2/batch/scrape/123-456-789?skip=26",
  "data": [
    {
      "json": {
        "title": "Crea un ‘chat con el sitio web’ usando Groq Llama 3 | Firecrawl",
        "description": "Aprende a usar Firecrawl, Groq Llama 3 y LangChain para crear un bot de ‘chat con tu sitio web’."
      }
    },
    ...
  ]
}
```

`startBatchScrape` / `start_batch_scrape` devuelve un ID de tarea:

```json
{
  "success": true,
  "id": "123-456-789",
  "url": "https://api.firecrawl.dev/v2/batch/scrape/123-456-789"
}
```

<div id="webhooks">
  ## Webhooks [#webhooks]
</div>

Puedes configurar webhooks para recibir notificaciones en tiempo real a medida que se rastrea cada URL de tu lote. Esto te permite procesar los resultados de inmediato en lugar de esperar a que finalice todo el lote.

```bash title="cURL"
curl -X POST https://api.firecrawl.dev/v2/batch/scrape \
    -H 'Content-Type: application/json' \
    -H 'Authorization: Bearer YOUR_API_KEY' \
    -d '{
      "urls": [
        "https://example.com/page1",
        "https://example.com/page2",
        "https://example.com/page3"
      ],
      "webhook": {
        "url": "https://your-domain.com/webhook",
        "metadata": {
          "any_key": "any_value"
        },
        "events": ["started", "page", "completed"]
      }
    }'
```

<div id="event-types">
  ### Tipos de eventos [#tipos-de-eventos]
</div>

| Evento                   | Descripción                                        |
| ------------------------ | -------------------------------------------------- |
| `batch_scrape.started`   | El proceso de scraping por lotes ha comenzado      |
| `batch_scrape.page`      | Se ha hecho scraping correctamente de una sola URL |
| `batch_scrape.completed` | Se han procesado todas las URL                     |
| `batch_scrape.failed`    | Se produjo un error durante el scraping por lotes  |

<div id="payload">
  ### Carga útil [#carga-útil]
</div>

Cada entrega de webhook incluye un cuerpo JSON con la siguiente estructura:

```json
{
  "success": true,
  "type": "batch_scrape.page",
  "id": "batch-job-id",
  "data": [...],
  "metadata": {},
  "error": null
}
```

<div id="verifying-webhook-signatures">
  ### Verificación de firmas de webhooks [#verificación-de-firmas-de-webhooks]
</div>

Cada solicitud de webhook de Firecrawl incluye un encabezado `X-Firecrawl-Signature` que contiene una firma HMAC-SHA256. Verifica siempre esta firma para asegurarte de que el webhook sea auténtico y no haya sido manipulado.

1. Obtén tu secreto de webhook en la [pestaña Advanced](https://www.firecrawl.dev/app/settings?tab=advanced) de la configuración de tu cuenta
2. Extrae la firma del encabezado `X-Firecrawl-Signature`
3. Calcula el HMAC-SHA256 del cuerpo sin procesar de la solicitud usando tu secreto
4. Compáralo con el encabezado de firma utilizando una función segura frente a ataques de temporización

<Warning>
  Nunca proceses un webhook sin verificar primero su firma. El encabezado `X-Firecrawl-Signature` contiene la firma en el formato: `sha256=abc123def456...`
</Warning>

Para ejemplos completos de implementación en JavaScript y Python, consulta la [documentación de seguridad de webhooks](/es/webhooks/security).

Para obtener una documentación completa sobre webhooks, incluidas cargas útiles de eventos detalladas, configuración avanzada y solución de problemas, consulta la [documentación de webhooks](/es/webhooks/overview).

> ¿Eres un agente de IA que necesita una clave de API de Firecrawl? Consulta [firecrawl.dev/agent-onboarding/SKILL.md](https://www.firecrawl.dev/agent-onboarding/SKILL.md) para obtener instrucciones de incorporación automatizada.
