> ## 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`.

# Fetch a page with a PUT

> Send a PUT to the target through Zenrows. Takes the same query parameters as fetchPage; the request body is forwarded to the target as is, and the response carries the target's content.



## OpenAPI

````yaml /api-reference/openapi.json put /
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:
  /:
    parameters:
      - name: url
        in: query
        description: The URL of the page to retrieve.
        required: true
        schema:
          type: string
          format: uri
          examples:
            - https://www.scrapingcourse.com/ecommerce/
        example: https://www.scrapingcourse.com/ecommerce/
      - name: mode
        in: query
        description: >-
          Adaptive Stealth Mode. `auto` starts from the cheapest viable
          configuration and escalates to JavaScript rendering or premium proxies
          only when the target requires it. You are billed for the configuration
          that succeeds.
        required: false
        schema:
          type: string
          enum:
            - auto
      - name: js_render
        in: query
        description: >-
          Render the page in a headless browser before returning it. Required
          for content that only exists after JavaScript runs.
        required: false
        schema:
          type: boolean
          default: false
      - name: js_instructions
        in: query
        description: >-
          JSON array of browser instructions (click, fill, scroll, wait)
          executed on the page before the content is returned. Requires
          js_render.
        required: false
        schema:
          type: string
      - name: custom_headers
        in: query
        description: Forward your own request headers (cookies, referer) to the target.
        required: false
        schema:
          type: boolean
          default: false
      - name: premium_proxy
        in: query
        description: >-
          Route the request through residential IPs. Required by most protected
          sites.
        required: false
        schema:
          type: boolean
          default: false
      - name: proxy_country
        in: query
        description: Two-letter country code for the exit IP. Requires premium_proxy.
        required: false
        schema:
          type: string
          pattern: ^[a-z]{2}$
          examples:
            - us
        example: us
      - name: session_id
        in: query
        description: >-
          Reuse the same IP across requests for up to 10 minutes. Any integer
          you choose identifies the session.
        required: false
        schema:
          type: integer
      - name: original_status
        in: query
        description: Return the target's own HTTP status code instead of the Zenrows one.
        required: false
        schema:
          type: boolean
          default: false
      - name: allowed_status_codes
        in: query
        description: >-
          Comma-separated status codes whose body should be returned instead of
          raising an error, for example `404,500`.
        required: false
        schema:
          type: string
      - name: wait_for
        in: query
        description: CSS selector to wait for before returning. Requires js_render.
        required: false
        schema:
          type: string
      - name: wait
        in: query
        description: Milliseconds to wait after load before returning. Requires js_render.
        required: false
        schema:
          type: integer
          default: 0
          minimum: 0
      - name: block_resources
        in: query
        description: >-
          Comma-separated resource types to block (for example
          `image,media,font`). Blocking is on by default.
        required: false
        schema:
          type: string
      - name: json_response
        in: query
        description: >-
          Return a JSON envelope that also carries the network requests
          (XHR/fetch) the page made.
        required: false
        schema:
          type: string
      - name: css_extractor
        in: query
        description: >-
          JSON object mapping output keys to CSS selectors, applied to the
          retrieved page.
        required: false
        schema:
          type: string
          examples:
            - '{"title":"h1","price":".price"}'
        example: '{"title":"h1","price":".price"}'
      - name: extract
        in: query
        description: >-
          Return structured JSON extracted from the page with no selectors to
          write (Extract). Omit it and Extract is off. `auto` and `native`
          return the website's own field names; `standard` returns a canonical
          schema shared by every website in a vertical (real estate only for
          now). Extract works on any prepared domain, with any active API key
          (prepare a new one with `POST /extract/prepared-domains`), and is
          currently free on top of the Fetch cost. A domain, or a kind of page
          on it, that is not prepared yet answers 403 `REQS007`: see
          `requestExtractDomain`.
        required: false
        schema:
          type: string
          enum:
            - auto
            - native
            - standard
      - name: extract_fields
        in: query
        description: >-
          Comma-separated list of the fields `extract` should return,
          dot-notated for fields inside a group (for example
          `products.name,products.price`). Omit it to receive every field.
        required: false
        schema:
          type: string
          examples:
            - products.name,products.price
        example: products.name,products.price
      - name: autoparse
        in: query
        description: >-
          Deprecated in favour of Extract (`extract=auto`). Returns
          general-purpose JSON parsed from the page, not tailored to the
          website.
        required: false
        schema:
          type: boolean
          default: false
        deprecated: true
      - name: response_type
        in: query
        description: 'Convert the page before returning it: Markdown, plaintext or PDF.'
        required: false
        schema:
          type: string
          enum:
            - markdown
            - plaintext
            - pdf
      - name: screenshot
        in: query
        description: Return an above-the-fold screenshot of the page. Requires js_render.
        required: false
        schema:
          type: boolean
          default: false
      - name: screenshot_fullpage
        in: query
        description: Return a full-page screenshot. Requires js_render.
        required: false
        schema:
          type: boolean
          default: false
      - name: screenshot_selector
        in: query
        description: >-
          Screenshot only the element matching this CSS selector. Requires
          js_render.
        required: false
        schema:
          type: string
      - name: screenshot_format
        in: query
        description: Screenshot image format.
        required: false
        schema:
          type: string
          enum:
            - png
            - jpeg
          default: png
      - name: screenshot_quality
        in: query
        description: JPEG quality, 1 to 100. Only with screenshot_format=jpeg.
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 100
      - name: outputs
        in: query
        description: >-
          Comma-separated data types to pull out of the retrieved HTML (for
          example `emails,phone_numbers`).
        required: false
        schema:
          type: string
    put:
      tags:
        - Fetch
      summary: Fetch a page with a PUT
      description: >-
        Send a PUT to the target through Zenrows. Takes the same query
        parameters as fetchPage; the request body is forwarded to the target as
        is, and the response carries the target's content.
      operationId: fetchPagePut
      requestBody:
        description: Forwarded to the target as is.
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              additionalProperties: true
          application/json:
            schema: {}
          '*/*':
            schema:
              type: string
      responses:
        '200':
          description: >-
            The target's content, in the shape the request asked for: HTML by
            default, Markdown or plaintext with `response_type`, a PDF or
            PNG/JPEG binary for `response_type=pdf` and the screenshot
            parameters, and JSON for `extract`, `css_extractor`, `autoparse` or
            `json_response`.
          content:
            text/html:
              schema:
                type: string
                description: The page as returned by the target.
              example: |-
                <!doctype html>
                <html lang="en-US">
                <head>
                <title>Ecommerce Test Site to Learn Web Scraping</title>
                </head>
                <body>
                <h1>Shop</h1>
                ...
                </body>
                </html>
            text/markdown:
              schema:
                type: string
                description: The page converted to Markdown.
              example: >-
                [Ecommerce Test Site to Learn Web
                Scraping](https://www.scrapingcourse.com/ecommerce/)


                # Shop


                - [Abominable
                Hoodie](https://www.scrapingcourse.com/ecommerce/product/abominable-hoodie/)
                $69.00

                ...
            text/plain:
              schema:
                type: string
                description: The page as plaintext.
              example: |-
                Ecommerce Test Site to Learn Web Scraping
                Shop
                Abominable Hoodie $69.00
                ...
            application/json:
              schema:
                type: object
                description: >-
                  Structured output: the extracted fields, the autoparsed
                  record, or the JSON envelope with captured network requests.
                additionalProperties: true
              example:
                html: |-
                  <!doctype html>
                  <html lang="en-US">...</html>
                parsed:
                  breadcrumbs:
                    - name: Home
                      position: 1
                      url: https://www.scrapingcourse.com/ecommerce
                  product:
                    name: Abominable Hoodie
                    availability: out_of_stock
                    category: Hoodies & Sweatshirts
            application/pdf:
              schema:
                type: string
                format: binary
                description: The page rendered to PDF.
            image/png:
              schema:
                type: string
                format: binary
                description: Screenshot of the page or of the selected element.
          headers:
            Concurrency-Limit:
              $ref: '#/components/headers/ConcurrencyLimit'
            Concurrency-Remaining:
              $ref: '#/components/headers/ConcurrencyRemaining'
            X-Request-Cost:
              $ref: '#/components/headers/XRequestCost'
            X-Request-Credits:
              $ref: '#/components/headers/XRequestCredits'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
        '400':
          description: The request is malformed, or a parameter combination is not allowed.
          headers:
            Concurrency-Limit:
              $ref: '#/components/headers/ConcurrencyLimit'
            Concurrency-Remaining:
              $ref: '#/components/headers/ConcurrencyRemaining'
            X-Request-Cost:
              $ref: '#/components/headers/XRequestCost'
            X-Request-Credits:
              $ref: '#/components/headers/XRequestCredits'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                code: REQS004
                instance: /v1
                status: 400
                title: >-
                  Invalid value provided for 'js_render' parameter; invalid
                  boolean value 'maybe' (REQS004)
                type: https://docs.zenrows.com/api-error-codes#REQS004
        '401':
          description: The API key is missing or invalid.
          headers:
            Concurrency-Limit:
              $ref: '#/components/headers/ConcurrencyLimit'
            Concurrency-Remaining:
              $ref: '#/components/headers/ConcurrencyRemaining'
            X-Request-Cost:
              $ref: '#/components/headers/XRequestCost'
            X-Request-Credits:
              $ref: '#/components/headers/XRequestCredits'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                code: AUTH002
                detail: Invalid API key.
                instance: /v1
                status: 401
                title: Invalid apikey provided (AUTH002)
                type: https://docs.zenrows.com/api-error-codes#AUTH002
        '402':
          description: >-
            The account is out of credits, or the plan does not include this
            capability.
          headers:
            Concurrency-Limit:
              $ref: '#/components/headers/ConcurrencyLimit'
            Concurrency-Remaining:
              $ref: '#/components/headers/ConcurrencyRemaining'
            X-Request-Cost:
              $ref: '#/components/headers/XRequestCost'
            X-Request-Credits:
              $ref: '#/components/headers/XRequestCredits'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                code: AUTH004
                detail: >-
                  This account has used all its credits for the period. Upgrade
                  or add credits to continue.
                instance: /v1
                status: 402
                title: Usage exceeded (AUTH004)
                type: https://docs.zenrows.com/api-error-codes#AUTH004
        '403':
          description: >-
            With `extract=auto`, error `REQS007`: the domain, or this kind of
            page on it, has not been prepared for Extract yet. The message names
            the domain. The request is not charged and no HTML is returned.
            Prepare the domain with `requestExtractDomain`, then retry once it
            reports `ready`. Documented at
            https://docs.zenrows.com/api-error-codes#REQS007.
          headers:
            Concurrency-Limit:
              $ref: '#/components/headers/ConcurrencyLimit'
            Concurrency-Remaining:
              $ref: '#/components/headers/ConcurrencyRemaining'
            X-Request-Cost:
              $ref: '#/components/headers/XRequestCost'
            X-Request-Credits:
              $ref: '#/components/headers/XRequestCredits'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                code: REQS007
                detail: >-
                  Extract has not been prepared for example.org yet. Ask for it
                  with POST /v1/extract/prepared-domains, then retry once it
                  reports ready. GET /v1/extract/domains lists what Extract
                  serves today.
                instance: /v1
                status: 403
                title: >-
                  Extract is not prepared for the requested domain (example.org)
                  (REQS007)
                type: https://docs.zenrows.com/api-error-codes#REQS007
        '422':
          description: >-
            Zenrows reached the target but could not return it under the
            requested configuration. With `extract`, the lowercase code
            `no_data_extracted` means something else: Extract knows this kind of
            page and applied its extraction, but no field came back filled. That
            answer is not charged, carries no HTML, and comes back the same on a
            retry, so do not retry it; check that the page rendered fully
            instead. The lowercase code `blocked_document` means the page
            Zenrows fetched was a bot challenge, an error page or a page that
            had not finished loading, so Extract had nothing real to read. It is
            not charged either; retry with `js_render=true` and/or
            `premium_proxy=true`, or with Adaptive Stealth Mode (`mode=auto`).
            Documented at
            https://docs.zenrows.com/api-error-codes#no_data_extracted.
          headers:
            Concurrency-Limit:
              $ref: '#/components/headers/ConcurrencyLimit'
            Concurrency-Remaining:
              $ref: '#/components/headers/ConcurrencyRemaining'
            X-Request-Cost:
              $ref: '#/components/headers/XRequestCost'
            X-Request-Credits:
              $ref: '#/components/headers/XRequestCredits'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                code: RESP001
                detail: >-
                  The target could not be returned under this configuration. Try
                  js_render=true and premium_proxy=true, or mode=auto.
                instance: /v1
                status: 422
                title: Could not get content (RESP001)
                type: https://docs.zenrows.com/api-error-codes#RESP001
        '429':
          description: >-
            Error `AUTH008`: every concurrency slot on the plan is occupied.
            There is no fixed requests-per-minute quota to wait out and no
            Retry-After to read: a slot frees when one of your requests in
            flight finishes. Read `Concurrency-Remaining` on any response to
            pace yourself, and back off exponentially before retrying.
            Documented at https://docs.zenrows.com/api-error-codes#AUTH008 and
            https://docs.zenrows.com/fetch/features/concurrency.
          headers:
            Concurrency-Limit:
              $ref: '#/components/headers/ConcurrencyLimit'
            Concurrency-Remaining:
              $ref: '#/components/headers/ConcurrencyRemaining'
            X-Request-Cost:
              $ref: '#/components/headers/XRequestCost'
            X-Request-Credits:
              $ref: '#/components/headers/XRequestCredits'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                code: AUTH008
                detail: >-
                  Every concurrency slot on the plan is in use. Retry when a
                  request in flight finishes.
                instance: /v1
                status: 429
                title: Concurrency limit reached (AUTH008)
                type: https://docs.zenrows.com/api-error-codes#AUTH008
components:
  headers:
    ConcurrencyLimit:
      description: >-
        Concurrent requests this plan allows. The rate limit, in the unit
        Zenrows meters: slots in flight, not requests per interval.
      schema:
        type: integer
        example: 20
    ConcurrencyRemaining:
      description: >-
        Free slots at the moment the request was received. Zero means the next
        request is refused with 429 until one finishes.
      schema:
        type: integer
        example: 17
    XRequestCost:
      description: >-
        Cost of this request in US dollars at your plan's price per credit, so
        it varies with the features the request enabled. `0` when the request is
        not charged. For the number of credits, read `X-Request-Credits`.
      schema:
        type: number
        example: 0.001
    XRequestCredits:
      description: >-
        Credits charged for this request. Requests that fail, and Extract
        refusals such as `REQS007`, `no_data_extracted` and `blocked_document`,
        are not charged.
      schema:
        type: integer
        example: 5
    XRequestId:
      description: Identifier for this request. Quote it when reporting a problem.
      schema:
        type: string
        example: 67fa4e35647515d8ad61bb3ee041e1bb
  schemas:
    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
  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`.

````

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