# Scrape JavaScript-rendered and anti-bot pages with Zenrows's API

Zenrows's Fetch returns pages that build their content in the browser or challenge ordinary clients. Set `js_render=true` to load the page in a headless browser, `premium_proxy=true` to route it through residential IPs, or `mode=auto` to let Fetch start with the cheapest configuration and step up only when the page needs it. A page draws 1 credit plain, 5 rendered, 10 through premium proxies and 25 with both, at $0.50 per thousand credits, and only successful requests are charged. Send `GET https://agents.zenrows.com/zcj/aj7ku22e8gd3/v1/?url=<page>` with `Authorization: Bearer <token>` for an agent credential that holds a plan.

## At a glance

- **Endpoint:** `GET https://agents.zenrows.com/zcj/aj7ku22e8gd3/v1/?url=<URL-encoded page>`, one page per request. POST and PUT pass a body through to the target.
- **Levers:** `js_render=true` (5 credits), `premium_proxy=true` (10), both (25), or `mode=auto`. A standard page is 1 credit.
- **Price:** $0.50 per thousand credits, so a page with both levers costs $0.0125.
- **Access:** `Authorization: Bearer <token>` for an agent credential that holds a plan. There is no per-call payment.
- **Payment:** a plan, bought by wallet (x402 or MPP, in USDC) or by card. Plan ids are in [the catalog](https://agents.zenrows.com/zcj/aj7ku22e8gd3/manifest.json).
- **Response:** the page as HTML by default, or as Markdown with `response_type=markdown`. The `zc-billing` header states what your balance was debited.
- **Charging:** only successful requests draw credit.
- **Full purchase flow:** [the buyer skill](https://agents.zenrows.com/zcj/aj7ku22e8gd3/SKILL.md)

## Fetch a page that builds its content with JavaScript

Start plain. The response shows whether the page needs a browser.

1. Send the page without rendering:

   ```bash
   curl -s "https://agents.zenrows.com/zcj/aj7ku22e8gd3/v1/?url=https%3A%2F%2Fwww.scrapingcourse.com%2Fjavascript-rendering&response_type=markdown" \
     -H "Authorization: Bearer $ACCESS_TOKEN"
   ```

   On this practice page, the 200 response is the empty shell: a prompt to enable JavaScript and a row of empty links. It still drew $0.0005, one credit, because the request succeeded.

2. Add `js_render=true` and a `wait_for` selector that only exists once the products have loaded:

   ```bash
   curl -s "https://agents.zenrows.com/zcj/aj7ku22e8gd3/v1/?url=https%3A%2F%2Fwww.scrapingcourse.com%2Fjavascript-rendering&js_render=true&wait_for=.product-name&response_type=markdown" \
     -H "Authorization: Bearer $ACCESS_TOKEN"
   ```

   The response lists the products, such as `Chaz Kangeroo Hoodie` and `Teton Pullover Hoodie`, and drew $0.0025, five credits. Choose the selector with care. The page's empty placeholders already carry `.product-item`, so waiting on that selector returns before the products load, and `.product-name` does not.

## Fetch a page behind an anti-bot challenge

1. Send the page plain:

   ```bash
   curl -s "https://agents.zenrows.com/zcj/aj7ku22e8gd3/v1/?url=https%3A%2F%2Fwww.scrapingcourse.com%2Fantibot-challenge" \
     -H "Authorization: Bearer $ACCESS_TOKEN"
   ```

   The answer is a 400 that names the parameters the page needs:

   ```json
   {"code": "REQS002", "title": "Www.scrapingcourse.com requires javascript rendering and premium proxies enabled…", "detail": "The requested URL domain needs JavaScript rendering and/or Premium Proxies due t…", "status": 400}
   ```

   A failed request is not charged.

2. Let Fetch choose the configuration by adding `mode=auto`:

   ```bash
   curl -s "https://agents.zenrows.com/zcj/aj7ku22e8gd3/v1/?url=https%3A%2F%2Fwww.scrapingcourse.com%2Fantibot-challenge&mode=auto&response_type=markdown" \
     -H "Authorization: Bearer $ACCESS_TOKEN"
   ```

   The page comes back with its content, `## You bypassed the Antibot challenge! :D`.

3. Or set both levers yourself:

   ```bash
   curl -s "https://agents.zenrows.com/zcj/aj7ku22e8gd3/v1/?url=https%3A%2F%2Fwww.scrapingcourse.com%2Fantibot-challenge&js_render=true&premium_proxy=true&response_type=markdown" \
     -H "Authorization: Bearer $ACCESS_TOKEN"
   ```

   This returns the same page content and drew $0.0125, 25 credits.

## Choose what to add

| The page | Set | Credits | Cost per page |
| --- | --- | --- | --- |
| Returns its content to a plain request | nothing | 1 | $0.0005 |
| Builds its content with JavaScript | `js_render=true` | 5 | $0.0025 |
| Needs a residential IP | `premium_proxy=true` | 10 | $0.005 |
| Challenges ordinary clients | `js_render=true&premium_proxy=true` | 25 | $0.0125 |

When you don't know what a page needs, set `mode=auto` and Fetch chooses. Screenshots and PDF renders need `js_render=true`.

## Control the render and the route

| To | Set |
| --- | --- |
| Wait for an element before returning | `wait_for=<CSS selector>` |
| Wait a fixed time after load | `wait=<milliseconds>` |
| Click, fill, scroll or wait in the page first | `js_instructions=<JSON array>` |
| Choose which resource types to block (blocking is on by default) | `block_resources=image,media,font` |
| Exit from one of 190 countries | `proxy_country=us` (two letters, with `premium_proxy=true`) |
| Keep the same IP for up to ten minutes | `session_id=<any integer>`, the same on each request |
| Forward your own headers, such as cookies or referer | `custom_headers=true`, then send the headers |

`wait`, `wait_for` and `js_instructions` require `js_render=true`. URL-encode each query value once.

## What is charged and when

- Every call draws on a plan your credential holds: the Free trial ($2.50 of credit, once per human with a verified email), Credits (from $5), or a monthly plan such as Launch at $69 a month.
- Only successful requests draw credit.
- Each request fetches one page, by its URL.

## Errors

| Status and code | Meaning | Action |
| --- | --- | --- |
| `400 REQS002` | The page needs JavaScript rendering and/or premium proxies | Add `js_render=true&premium_proxy=true`, or `mode=auto` |
| `422 RESP001` | The page could not be returned under this configuration | Add both levers, or `mode=auto` |
| `401 bearer_required` | No agent credential on the call | Register one at [auth.md](https://agents.zenrows.com/zcj/aj7ku22e8gd3/auth.md), then retry with the bearer |
| `403 plan_required` | The credential holds no plan that covers the call | Buy one of the plans the body lists, then retry |
| `usage_exhausted` | The plan's credit is used up | Top up with `POST https://agents.zenrows.com/zcj/aj7ku22e8gd3/extend` and `{"amountUsd": "..."}` |
| `429 AUTH008` | Every concurrency slot on the plan is in use | Wait for a request in flight to finish, and back off before retrying |

## Frequently asked questions

### Why does my scraping request return an empty page?

The page builds its content with JavaScript, so a plain request gets the shell before any content loads. Add `js_render=true` and a `wait_for` selector that appears only once the content is there. A selector that the empty page already contains returns too early.

### Should I use mode=auto or set js_render and premium_proxy myself?

Use `mode=auto` when you don't know what a page needs. It starts with the cheapest configuration and steps up to rendering or premium proxies only when the page requires it. Set the levers yourself when you already know what the page needs.

### Can mode=auto be combined with wait_for or proxy_country?

Yes. With `mode=auto`, Fetch manages `js_render` and `premium_proxy` for you. Setting `wait` or `wait_for` makes it apply JavaScript rendering, and setting `proxy_country` makes it apply premium proxies. `css_extractor`, `session_id` and custom headers work alongside it.

### How long does a rendered or protected request take?

It depends on the page. On the practice pages above, the rendered request took 5.5 seconds and the anti-bot page with both levers took 13.0 seconds.

### Is a blocked or failed request charged?

No. Only successful requests draw credit. The `zc-billing` header on a response states what your balance was debited.

## Keep reading

- [Buyer skill](https://agents.zenrows.com/zcj/aj7ku22e8gd3/SKILL.md): the full purchase flow
- [Identity](https://agents.zenrows.com/zcj/aj7ku22e8gd3/auth.md): register and claim an agent credential
- [How to pay](https://agents.zenrows.com/zcj/aj7ku22e8gd3/payment.md): plans, rails and top-ups
- [Fetch API reference](https://agents.zenrows.com/zcj/aj7ku22e8gd3/services/fetch/openapi.json): every parameter
- [Error reference](https://agents.zenrows.com/zcj/aj7ku22e8gd3/errors.md): every storefront error code

---

Updated 2026-10-30. All Zenrows guides: https://agents.zenrows.com/guides.md. Storefront: https://agents.zenrows.com/zcj/aj7ku22e8gd3/llms.txt.
