# Download batch scrape results (/docs/reference/download-batch-scrape)

Redirects to a gzipped NDJSON file of the batch scrape's results: one document per line, in URL order, failed and cancelled URLs included. Use the url from the status package, whose token is the capability: no API key is needed. Each download counts against the batch scrape's own result-read quota.

`GET /v2/batch/scrape/{id}/download`

An API key is optional; without one the caller is anonymous.

## Example request

```sh
curl 'https://api.elisebot.dev/v2/batch/scrape/<id>/download' \
  -H "Authorization: Bearer $ELISEBOT_API_KEY"
```

## Parameters

- `id` (path, string, required): The batch scrape ID.
- `token` (query, string, required): The download token, as the status package url carries it. At least 1 characters.

## Responses

### 302

The package is ready: Location is a presigned URL, valid for 5 minutes, that serves the gzipped NDJSON file as an attachment.

Headers:

- `Location` (string): The presigned URL of the package.

### 401

UNAUTHORIZED: The API key is invalid or revoked; API_KEY_REQUIRED: This endpoint needs an API key; INVALID_ACCESS_TOKEN: The OAuth access token is unknown, expired or revoked, or was sent to an endpoint other than /mcp, the only one it works on.

Type: `UnauthorizedResponse`

- `code` (string, required): A machine-readable error code. One of `UNAUTHORIZED`, `API_KEY_REQUIRED`, `INVALID_ACCESS_TOKEN`.
- `details` (array of ValidationErrorDetail or null): The invalid fields.
  - `location` (string): Where the error occurred, e.g. body.urls[3].
  - `message` (string): What went wrong.
  - `value` (any): The rejected value.
- `error` (string, required): A human-readable message.
- `success` (boolean, required): Always false. One of `false`.

### 404

SCRAPE_NOT_FOUND: The scrape does not exist, has expired or is another caller's; BATCH_SCRAPE_NOT_FOUND: The batch scrape does not exist, has expired or is another caller's, or the download token does not match.

Type: `NotFoundResponse`

- `code` (string, required): A machine-readable error code. One of `SCRAPE_NOT_FOUND`, `BATCH_SCRAPE_NOT_FOUND`.
- `details` (array of ValidationErrorDetail or null): The invalid fields.
  - `location` (string): Where the error occurred, e.g. body.urls[3].
  - `message` (string): What went wrong.
  - `value` (any): The rejected value.
- `error` (string, required): A human-readable message.
- `success` (boolean, required): Always false. One of `false`.

### 409

BATCH_SCRAPE_NOT_CANCELLABLE: The batch scrape already completed and cannot be cancelled; PACKAGE_NOT_READY: The batch scrape's results are still being packaged; poll the status until package.status is ready; PACKAGE_FAILED: Packaging the batch scrape's results failed for good; the batch scrape's credits were refunded.

Type: `ConflictResponse`

- `code` (string, required): A machine-readable error code. One of `BATCH_SCRAPE_NOT_CANCELLABLE`, `PACKAGE_NOT_READY`, `PACKAGE_FAILED`.
- `details` (array of ValidationErrorDetail or null): The invalid fields.
  - `location` (string): Where the error occurred, e.g. body.urls[3].
  - `message` (string): What went wrong.
  - `value` (any): The rejected value.
- `error` (string, required): A human-readable message.
- `success` (boolean, required): Always false. One of `false`.

### 422

VALIDATION_FAILED: One or more fields are invalid; TOO_MANY_URLS: The request has more URLs than your rate limit allows; IDEMPOTENCY_CONFLICT: The Idempotency-Key was already used with a different request.

Type: `ValidationFailedResponse`

- `code` (string, required): A machine-readable error code. One of `VALIDATION_FAILED`, `TOO_MANY_URLS`, `IDEMPOTENCY_CONFLICT`.
- `details` (array of ValidationErrorDetail or null): The invalid fields.
  - `location` (string): Where the error occurred, e.g. body.urls[3].
  - `message` (string): What went wrong.
  - `value` (any): The rejected value.
- `error` (string, required): A human-readable message.
- `success` (boolean, required): Always false. One of `false`.

### 429

RATE_LIMITED: Rate limit exceeded, retry after Retry-After seconds.

Headers:

- `Retry-After` (integer): Seconds to wait before retrying. Minimum 1.

Type: `TooManyRequestsResponse`

- `code` (string, required): A machine-readable error code. One of `RATE_LIMITED`.
- `details` (array of ValidationErrorDetail or null): The invalid fields.
  - `location` (string): Where the error occurred, e.g. body.urls[3].
  - `message` (string): What went wrong.
  - `value` (any): The rejected value.
- `error` (string, required): A human-readable message.
- `success` (boolean, required): Always false. One of `false`.

### 500

INTERNAL_ERROR: Something went wrong on our side, try again.

Type: `InternalErrorResponse`

- `code` (string, required): A machine-readable error code. One of `INTERNAL_ERROR`.
- `details` (array of ValidationErrorDetail or null): The invalid fields.
  - `location` (string): Where the error occurred, e.g. body.urls[3].
  - `message` (string): What went wrong.
  - `value` (any): The rejected value.
- `error` (string, required): A human-readable message.
- `success` (boolean, required): Always false. One of `false`.
