> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zenrows.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> The Zenrows API (Fetch, Extract, Crawl and Batch) is described in OpenAPI 3.1 at https://www.zenrows.com/openapi.json and listed in the RFC 9727 API catalog at https://www.zenrows.com/.well-known/api-catalog. Every endpoint also has its own page under /api-reference with its schema. Use the spec for exact parameter names and types. To call Zenrows from an agent, connect the MCP server at https://mcp.zenrows.com/mcp. To search these docs from an agent, connect the docs MCP server at https://docs.zenrows.com/mcp. Agent skills for Zenrows are published at https://github.com/ZenRows/cli and install with `npx skills add ZenRows/cli`.

# Create a batch job (many URLs in one request)

> Submit a job. A closed job carries all its URLs up front in `tasks`; an open job (`status: open`) is created empty and receives URLs through addBatchTasks until one call sets `last_batch`. A scheduled job (`type: scheduled`) stores its URLs as a template and each fire creates a run. `zenrows_params` applies to every task and a per-task `zenrows_params` overrides it. Returns 201 under 10,000 inline tasks and 202 at or above that (or for a CSV input); the body is identical, so treat both the same. Documented at https://docs.zenrows.com/batch/developer-guide-restapi#1-create-your-jobs.



## OpenAPI

````yaml /api-reference/openapi.json post /jobs
openapi: 3.1.0
info:
  title: Zenrows API
  version: 1.0.0
  summary: >-
    Reach any page, including the protected web, and return it as HTML,
    Markdown, plaintext, PDF or structured JSON.
  description: >-
    Zenrows is web data infrastructure for agents and applications. Three HTTP
    surfaces are described here:


    - **Fetch and Extract**: one synchronous request per page, at
    `https://api.zenrows.com/v1/`. Authentication is the `apikey` query
    parameter.

    - **Crawl**: collect the URLs behind one start page, at
    `https://api.zenrows.com/v1/crawls`. Authentication is the `X-API-Key`
    header or the `apikey` query parameter.

    - **Batch**: asynchronous jobs of up to 100,000 URLs, at
    `https://async.api.zenrows.com/v1`. Authentication is the `X-API-Key`
    header.


    **Browser** is not described here because it is not HTTP: you connect
    Puppeteer or Playwright to a WebSocket endpoint. See
    https://docs.zenrows.com/browser-sessions/introduction.


    **Cost.** A request costs 1 credit, 5 with JavaScript rendering, 10 with
    premium proxies, 25 with both, and 1 to 25 under `mode=auto`. Failed
    requests are never charged. The free tier is 5,000 credits a month, no card.


    **Versioning and deprecation.** The version is in the URL path (`/v1`, the
    only version so far). Inside a version Zenrows only adds: new endpoints,
    optional parameters, response fields and headers. Nothing is removed or
    changed. Retiring a version is announced at least twelve months ahead, and
    every response from a deprecated version carries the `Deprecation` (RFC
    9745) and `Sunset` (RFC 8594) headers. Policy:
    https://docs.zenrows.com/api-versioning.


    **Getting a key without a human.** `POST
    https://app.zenrows.com/api/agent/signup` returns a usable key; the spec is
    at https://www.zenrows.com/auth.md and a setup playbook at
    https://www.zenrows.com/SKILL.md.
  termsOfService: https://www.zenrows.com/legal/terms-of-use
  contact:
    name: Zenrows support
    email: support@zenrows.com
    url: https://www.zenrows.com/contact
  license:
    name: Proprietary
    url: https://www.zenrows.com/legal/terms-of-use
servers:
  - url: https://api.zenrows.com/v1
    description: Fetch and Extract (synchronous)
security:
  - apiKeyQuery: []
tags:
  - name: Fetch
    description: Retrieve one page, optionally rendered, proxied, converted or extracted.
  - name: Extract
    description: Which domains Extract serves, and getting a new one prepared.
  - name: Crawl
    description: Collect the URLs behind one start page, and each page's HTML when asked.
  - name: Batch
    description: Submit many URLs as one job and collect the results.
  - name: Account
    description: Plan, credits and concurrency for the calling key.
  - name: Onboarding
    description: Get a working key with no human in the loop.
externalDocs:
  description: Zenrows documentation
  url: https://docs.zenrows.com
paths:
  /jobs:
    post:
      tags:
        - Batch
      summary: Create a batch job (many URLs in one request)
      description: >-
        Submit a job. A closed job carries all its URLs up front in `tasks`; an
        open job (`status: open`) is created empty and receives URLs through
        addBatchTasks until one call sets `last_batch`. A scheduled job (`type:
        scheduled`) stores its URLs as a template and each fire creates a run.
        `zenrows_params` applies to every task and a per-task `zenrows_params`
        overrides it. Returns 201 under 10,000 inline tasks and 202 at or above
        that (or for a CSV input); the body is identical, so treat both the
        same. Documented at
        https://docs.zenrows.com/batch/developer-guide-restapi#1-create-your-jobs.
      operationId: createBatchJob
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          schema:
            type: string
          description: >-
            Optional guard against creating duplicate jobs. Each key can be used
            once: the first submit with a key creates the job, and any later
            submit reusing it returns 409 `idempotency_key_conflict`, whether or
            not the body is identical. The original response is not replayed, so
            this is not a safe-retry token: if a submit fails midway, list your
            recent jobs to see whether it was created, then reuse its `job_id`
            or submit again with a new key.
          example: nightly-2026-06-08
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - type
                - status
              properties:
                type:
                  type: string
                  enum:
                    - regular
                    - scheduled
                  description: >-
                    `regular` runs when submitted; `scheduled` runs on the
                    `schedule`.
                status:
                  type: string
                  enum:
                    - closed
                    - open
                  description: >-
                    `closed` carries every URL now; `open` accepts URLs over
                    time through addBatchTasks.
                name:
                  type: string
                  description: Your own label for the job.
                external_id:
                  type: string
                  description: Your own identifier for the job.
                metadata:
                  type: object
                  additionalProperties: true
                  description: Your own key-value data, returned with the job.
                zenrows_params:
                  type: object
                  description: >-
                    Fetch parameters applied to every task, with the names the
                    fetchPage operation uses.
                  additionalProperties: true
                tasks:
                  type: array
                  description: >-
                    The URLs to run, up to 100,000 per submit. Omit for an open
                    job and when `file_input_id` is set.
                  maxItems: 100000
                  items:
                    $ref: '#/components/schemas/BatchTask'
                file_input_id:
                  type: string
                  description: >-
                    From uploadBatchInput, to run the job from an uploaded CSV
                    instead of inline `tasks`. Always answers 202.
                schedule:
                  $ref: '#/components/schemas/BatchSchedule'
                webhook:
                  $ref: '#/components/schemas/BatchWebhook'
            example:
              type: regular
              status: closed
              zenrows_params:
                js_render: 'true'
                response_type: markdown
              tasks:
                - url: >-
                    https://www.scrapingcourse.com/ecommerce/product/abominable-hoodie/
                  external_id: sku-1042
                - url: >-
                    https://www.scrapingcourse.com/ecommerce/product/adrienne-trek-jacket/
                  external_id: sku-1043
                  zenrows_params:
                    proxy_country: de
      responses:
        '201':
          description: Job accepted, under 10,000 inline tasks.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JobSubmitted'
              example:
                job_id: 01M4E06YS7BDRECVN5QRHJA6HR
                status: closed
                accepted_tasks: 2
                latest_run:
                  run_id: 01M4E06YS7VZPY4G25DV6FR3B8
                  job_id: 01M4E06YS7BDRECVN5QRHJA6HR
                  run_sequence: 1
                  status: running
                  trigger: manual
                  last_batch_received: false
                  stats:
                    total: 2
                    completed: 0
                    successful: 0
                    failed: 0
                  created_at: '2026-10-08T14:55:52Z'
                  updated_at: '2026-10-08T14:56:06Z'
        '202':
          description: >-
            Job accepted, 10,000 tasks or more, or a CSV input. Task rows keep
            writing for a few seconds, so results pages can be partial at first,
            and addBatchTasks can answer 409 meanwhile.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JobSubmitted'
              example:
                job_id: 01M4E06YS7BDRECVN5QRHJA6HR
                status: closed
                accepted_tasks: 2
                latest_run:
                  run_id: 01M4E06YS7VZPY4G25DV6FR3B8
                  job_id: 01M4E06YS7BDRECVN5QRHJA6HR
                  run_sequence: 1
                  status: running
                  trigger: manual
                  last_batch_received: false
                  stats:
                    total: 2
                    completed: 0
                    successful: 0
                    failed: 0
                  created_at: '2026-10-08T14:55:52Z'
                  updated_at: '2026-10-08T14:56:06Z'
        '400':
          description: >-
            `invalid_argument`: validation failed. `invalid_tasks` lists each
            rejected task as `{index, reason}`. Documented at
            https://docs.zenrows.com/batch/developer-guide-restapi#error-handling-reference.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                code: invalid_argument
                detail: Validation failed.
                instance: /v1
                status: 400
                title: Validation failed (invalid_argument)
                type: https://docs.zenrows.com/api-error-codes#invalid_argument
        '401':
          description: '`unauthenticated`: the `X-API-Key` header is missing or invalid.'
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                code: unauthenticated
                detail: Invalid API key.
                instance: /v1
                status: 401
                title: Unauthenticated (unauthenticated)
                type: https://docs.zenrows.com/api-error-codes#unauthenticated
        '402':
          description: >-
            `payment_required` (no credits left) or `api_key_cap_reached` (the
            key hit a credit cap; `detail` names the cap and when it resets).
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                code: payment_required
                detail: No credits available.
                instance: /v1
                status: 402
                title: No credits available (payment_required)
                type: https://docs.zenrows.com/api-error-codes#payment_required
        '409':
          description: >-
            `idempotency_key_conflict`: the Idempotency-Key was already used. No
            job was created by this request.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                code: idempotency_key_conflict
                detail: Idempotency key already used.
                instance: /v1
                status: 409
                title: Idempotency key already used (idempotency_key_conflict)
                type: >-
                  https://docs.zenrows.com/api-error-codes#idempotency_key_conflict
        '429':
          description: >-
            `quota_exceeded`: the account already runs its active jobs (3 by
            default, shared with Crawl). Wait for one to end.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                code: quota_exceeded
                detail: Too many active jobs.
                instance: /v1
                status: 429
                title: Too many active jobs (quota_exceeded)
                type: https://docs.zenrows.com/api-error-codes#quota_exceeded
        '503':
          description: >-
            `internal`: a transient failure. Retry with backoff; for
            createBatchJob, list your jobs first, since the job may have been
            created.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                code: internal
                detail: Temporary failure, retry with backoff.
                instance: /v1
                status: 503
                title: Temporary failure, retry with backoff (internal)
                type: https://docs.zenrows.com/api-error-codes#internal
      security:
        - apiKeyHeader: []
      servers:
        - url: https://async.api.zenrows.com/v1
          description: Batch (asynchronous jobs)
components:
  schemas:
    BatchTask:
      type: object
      required:
        - url
      properties:
        url:
          type: string
          format: uri
        external_id:
          type: string
          description: Your own identifier, echoed on the result. Need not be unique.
        metadata:
          type: object
          additionalProperties: true
          description: Your own data, echoed on the result.
        zenrows_params:
          type: object
          additionalProperties: true
          description: Overrides the job-level parameters for this URL.
        method:
          type: string
          enum:
            - GET
            - POST
          default: GET
          description: '`POST` sends `body` to the target.'
        body:
          type: string
          maxLength: 16384
          description: 'Sent to the target as is, with `method: POST`. Up to 16 KiB.'
    BatchSchedule:
      type: object
      description: >-
        Exactly one of `at`, `rate` or `calendar`, plus `timezone` for `at` and
        `calendar`. Times of day are full hours; runs are at least 60 minutes
        apart.
      properties:
        at:
          type: object
          additionalProperties: true
          description: One run at a single wall-clock time.
        rate:
          type: object
          description: Every N hours.
          properties:
            every:
              type: integer
              minimum: 1
            unit:
              type: string
              enum:
                - hour
        calendar:
          type: object
          properties:
            times_of_day:
              type: array
              items:
                type: string
                pattern: ^[0-2][0-9]:00$
              description: Full hours, `HH:00`.
            cadence:
              type: object
              additionalProperties: true
              description: 'For example `{"weekly": {"days": ["mon", "wed", "fri"]}}`.'
        timezone:
          type: string
          description: IANA name, for example `Europe/Berlin`.
    BatchWebhook:
      type: object
      required:
        - url
      description: Where run notifications (`run.completed`, `run.failed`) are delivered.
      properties:
        url:
          type: string
          format: uri
          description: Your HTTPS receiver.
        signature:
          type: boolean
          description: >-
            Sign deliveries with your HMAC key (needs an active key, see
            startHmacKeyRotation).
    JobSubmitted:
      type: object
      description: The answer to createBatchJob.
      properties:
        job_id:
          type: string
        status:
          type: string
          enum:
            - open
            - closed
        accepted_tasks:
          type: integer
        webhook:
          $ref: '#/components/schemas/BatchWebhook'
        latest_run:
          $ref: '#/components/schemas/Run'
    Error:
      type: object
      description: >-
        Zenrows error envelope, sent as `application/problem+json` (RFC 9457
        problem details). `code` is the stable identifier to branch on; `type`
        links to its entry in the catalogue at
        https://docs.zenrows.com/api-error-codes. Read back from live responses.
      properties:
        code:
          type: string
          example: AUTH002
        status:
          type: integer
          example: 401
        title:
          type: string
          example: Invalid apikey provided (AUTH002)
        detail:
          type: string
          example: Invalid API key.
        type:
          type: string
          format: uri
          example: https://docs.zenrows.com/api-error-codes#AUTH002
        instance:
          type: string
          description: >-
            The request path or a request URN. Quote it when reporting a
            problem.
          example: /v1
    Run:
      type: object
      description: One run of a job.
      properties:
        run_id:
          type: string
        job_id:
          type: string
        run_sequence:
          type: integer
          description: 1 for the first run, then one more per rerun or scheduled fire.
        status:
          type: string
          enum:
            - pending
            - running
            - completed
            - failed
            - stopped
            - deleted
          description: '`completed`, `failed`, `stopped` and `deleted` are terminal.'
        pause_state:
          type: string
          enum:
            - active
            - paused
          description: '`paused` after pauseBatchRun; `status` does not change.'
        trigger:
          type: string
          enum:
            - manual
            - scheduled
          description: What started the run.
        last_batch_received:
          type: boolean
          description: 'Open jobs: whether the final addBatchTasks call arrived.'
        stats:
          type: object
          description: Task counters. `completed` is `successful` plus `failed`.
          properties:
            total:
              type: integer
            completed:
              type: integer
            successful:
              type: integer
            failed:
              type: integer
            spend:
              type: object
              description: Absent until there is spend.
              properties:
                credits:
                  type: integer
                cost:
                  type: number
                  description: US dollars.
        failure_reason:
          type: string
          description: Only when the whole run failed. Open set; new values may appear.
          examples:
            - insufficient_credits
            - subscription_inactive
            - api_key_cap_reached
        failure_detail:
          type: string
          description: What happened, for example which cap and when it resets.
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
  headers:
    XRequestId:
      description: Identifier for this request. Quote it when reporting a problem.
      schema:
        type: string
        example: 67fa4e35647515d8ad61bb3ee041e1bb
  securitySchemes:
    apiKeyQuery:
      type: apiKey
      in: query
      name: apikey
      description: >-
        Fetch, Extract, Crawl and the account endpoint accept the key as the
        `apikey` query parameter. Keys are per account and self-serve: create
        one in the Zenrows dashboard (app.zenrows.com), or, for an agent with no
        human present, `POST https://app.zenrows.com/api/agent/signup`.
    apiKeyHeader:
      type: apiKey
      in: header
      name: X-API-Key
      description: >-
        Batch, Crawl, the Extract endpoints and the account endpoint read the
        same key from the `X-API-Key` header.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.