# Migrating from ScrapingBee to Zyte API

Learn how to migrate from [ScrapingBee](https://www.scrapingbee.com/) to [Zyte API](../../get-started.md#zyte-api).

## Feature comparison

The following table summarizes the feature differences between both products:

| Feature                                                 | ScrapingBee                           | Zyte API                                                                                                                                     |
|---------------------------------------------------------|---------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------|
| Client software                                         | Python, NodeJS                        | [Python](https://python-zyte-api.readthedocs.io/en/stable/index.html), [Scrapy](https://scrapy-zyte-api.readthedocs.io/en/latest/index.html) |
| [Pricing](#spb-pricing)                                 | Fixed plans                           | Pay as you go Monthly commitment over $100                                                                                                   |
| [Ban avoidance](#spb-bans)                              | Manual, may increase costs            | Automatic, no extra costs                                                                                                                    |
| [Automatic extraction](#spb-extract)                    | Google SERP, custom LLM prompts       | Standard schemas including Google SERP, custom LLM prompts                                                                                   |
| [Geolocation](../../usage/features.md#zapi-geolocation) | 243 countries, no data center support | 249 countries, data center support                                                                                                           |
| Sessions                                                | Client-managed only (5m)              | Client-managed (15m) and server-managed                                                                                                      |
| [Actions](#spb-actions)                                 | Basic only (9)                        | Basic (15), advanced, website-specific and custom                                                                                            |
| Screenshots                                             | Yes, can target an element            | Yes, cannot target an element                                                                                                                |
| Body size limit                                         | 2 MB                                  | 10 MB                                                                                                                                        |
| Custom headers                                          | Yes                                   | Only in HTTP requests, limited to `Referer` in browser requests, cannot disable ban-avoidance headers                                        |
| Ad blocking                                             | Yes                                   | No                                                                                                                                           |
| Resource blocking                                       | Yes                                   | No                                                                                                                                           |
| Custom proxies                                          | Yes                                   | No                                                                                                                                           |
| Server-side CSS/XPath selectors                         | Yes                                   | No                                                                                                                                           |
| [Rate limiting](#spb-rate-limiting)                     | Concurrency-based                     | RPM-based                                                                                                                                    |
| Usage API                                               | Yes, up to 6 requests per second      | [Yes](../../usage/stats/index.md#stats-api), up to 20 requests per second                                                                    |

### Pricing

ScrapingBee offers 4 plans with a fixed price per month, each with a fixed
number of “credits” per month that you have to spend on that month or lose.

With Zyte API you pay only for what you use, up to a $100 monthly
[spending limit](../../pricing.md#zapi-spending-limit). If you need a higher spending
limit, you must commit to paying half as [monthly commitment](../../pricing.md#zapi-monthly-commitment), which you do not get back if you spend less during
a month.

With ScrapingBee, HTTP requests cost 1 credit each, while browser requests cost
5 credits each. If you need to use device residential IPs (“premium proxies”)
to avoid bans, costs raise to 10 credits per HTTP request (10×) and 25 credits
per browser request (5×). For scenarios where device residential IPs do not
avoid bans either, ScrapingBee offers special “stealth” proxies for browser
requests at 75 credits per request (15×). ScrapingBee also charges 20 credits
when targetting Google domains.

With Zyte API, request cost varies depending not only on the type of request
(HTTP or browser), but also on the [tier](../../pricing.md#tiers) of the target website,
which covers the cost of any tech that Zyte API may use to get you a ban-free
response, including browser rendering and device residential IPs. No extra cost
for Google domains; not even for automatic extraction of SERP
([serp](https://docs.zyte.com/zyte-api/usage/reference.html#operation/extract/request/serp)).

Unless you are never using premium or stealth proxies, you are targetting
mostly high-tier websites, and the number of credits per month that you need is
close to those included in one of ScrapingBee‘s plans, **Zyte API tends to be a
cheaper choice**.

For example, the $49 ScrapingBee plan includes 150k credits, i.e. 150k HTTP
requests. For tier 1-2 websites (i.e. most websites), Zyte API is cheaper. And
Zyte API can also be cheaper for higher-tier websites if you need fewer than
150k requests: 114k requests for tier 3, 70k requests for tier 2, and 39k
request for tier 5.

### Ban handling

ScrapingBee makes it your responsibility to choose the right technologies
(browser rendering, device residential IPs, “stealth IPs”) to avoid bans, with
the corresponding [cost increase](#spb-pricing).

Zyte API automatically chooses the leanest technology possible transparently,
without any extra cost, and automatically adapting to website changes.

### Automatic extraction

ScrapingBee supports automatic extraction through user-defined LLM prompts.

[Zyte API automatic extraction](../../usage/extract/index.md#zapi-extract) provides automatic
extraction for [supported types](../../usage/extract/index.md#zapi-extract-fields) *and* user-defined
LLM prompts to extract additional fields.

Both ScrapingBee and Zyte API support Google SERP extraction
([serp](https://docs.zyte.com/zyte-api/usage/reference.html#operation/extract/request/serp)).

### Rate limiting

ScrapingBee limits the number of concurrent requests that you can send,
starting at 5 with the most basic plan.

Zyte API limits the number of requests per minute (RPM) that you can send. It
is 3000 by default for all Zyte API keys, but [you can request a higher
limit](../../usage/rate-limit.md#rate-limit-increase).

For services like these that support advanced features like [browser
rendering](../../usage/browser.md#zapi-browser) or [automatic extraction](../../usage/extract/index.md#zapi-extract), which
usually increase response times, RPM rate limiting allows you to maintain your
throughput regardless of which features you use thanks to unlimited
concurrency, while concurrency-based limits slow down your crawls as you use
features that make requests slower.

For example, assuming an [HTTP request](../../usage/http.md#zapi-http) takes 2 seconds and a
[browser request](../../usage/browser.md#zapi-browser) takes 20 seconds, switching from HTTP
requests to browser requests with ScrapingBee would make your crawl 10 times
slower, while Zyte API would allow you to maintain a similar crawl speed by
using more concurrent requests to make up for the response time increase.

## Migrating

The main differences between the HTTP APIs of ScrapingBee and Zyte API are how
request parameters are defined and how the response is encoded.

In **ScrapingBee**, you send a `GET` request, and you specify parameters in
the URL query string, URL-encoded, e.g.

```bash
curl "https://app.scrapingbee.com/api/v1/?api_key=YOUR_ZYTE_API_KEY&url=https%3A%2F%2Ftoscrape.com"
```

The API response body comes straight from the target website:

```html
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Scraping Sandbox</title>
        …
```

HTTP response headers and cookies from the target website are also received as
regular headers and cookies, only prefixed with `Spb-`.

```none
Spb-Content-Encoding: br
Spb-Content-Type: text/html
```

In **Zyte API**, you send a `POST` request, and you specify parameters in the
request body as JSON, e.g.

> [!TIP]
> Same as ScrapingBee, Zyte API offers a [proxy mode](../../usage/proxy-mode.md#zapi-proxy)
> that you can use instead of the HTTP API if it makes things simpler.

```bash
curl \
    --user YOUR_ZYTE_API_KEY: \
    --header 'Content-Type: application/json' \
    --data '{"url": "https://toscrape.com", "httpResponseBody": true, "httpResponseHeaders": true}' \
    --compressed \
    https://api.zyte.com/v1/extract
```

The API response is a JSON object with all the response data from the target
website:

```json
{
    "url": "https://toscrape.com/",
    "statusCode": 200,
    "httpResponseBody": "PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ImVuIj4KICAgIDx…",
    "httpResponseHeaders": [
        {
            "name": "content-type",
            "value": "text/html"
        },
        {
            "name": "content-encoding",
            "value": "br"
        }
    ]
}
```

> [!NOTE]
> [httpResponseBody](https://docs.zyte.com/zyte-api/usage/reference.html#operation/extract/response/200/httpResponseBody) is base64-encoded to support binary
> responses, like images or PDF files.

Once you understand how to migrate a simple request like the one above, you can
migrate any other request the same way, [replacing ScrapingBee parameters
with Zyte API counterparts](#spb-params).

## Parameter mapping

| ScrapingBee               | Zyte API                                                                                                                                                                                                                                           |
|---------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| (default)                 | [httpResponseBody](https://docs.zyte.com/zyte-api/usage/reference.html#operation/extract/request/httpResponseBody), [httpResponseHeaders](https://docs.zyte.com/zyte-api/usage/reference.html#operation/extract/request/httpResponseHeaders)       |
| `api_key`                 | Use [basic authentication](../../usage/reference.md#zapi-auth)                                                                                                                                                                                     |
| `url`                     | [url](https://docs.zyte.com/zyte-api/usage/reference.html#operation/extract/request/url)                                                                                                                                                           |
| `render_js`               | [browserHtml](https://docs.zyte.com/zyte-api/usage/reference.html#operation/extract/request/browserHtml)                                                                                                                                           |
| `js_scenario`             | [See below](#spb-actions)                                                                                                                                                                                                                          |
| `wait`                    | `waitForTimeout` action ([see below](#spb-actions))                                                                                                                                                                                                |
| `wait_for`                | `waitForSelector` action ([see below](#spb-actions))                                                                                                                                                                                               |
| `wait_browser`            | `waitForNavigation` action ([see below](#spb-actions))                                                                                                                                                                                             |
| `block_ads`               | Not supported                                                                                                                                                                                                                                      |
| `block_resources`         | Not supported                                                                                                                                                                                                                                      |
| `viewport_width`          | [viewport](https://docs.zyte.com/zyte-api/usage/reference.html#operation/extract/request/viewport)                                                                                                                                                 |
| `window_height`           | [viewport](https://docs.zyte.com/zyte-api/usage/reference.html#operation/extract/request/viewport)                                                                                                                                                 |
| `premium_proxy`           | [ipType=residential](https://docs.zyte.com/zyte-api/usage/reference.html#operation/extract/request/ipType) (not required to [avoid bans](../../usage/errors.md#zapi-bans))                                                                         |
| `country_code`            | [geolocation](https://docs.zyte.com/zyte-api/usage/reference.html#operation/extract/request/geolocation) (does not require [ipType=residential](https://docs.zyte.com/zyte-api/usage/reference.html#operation/extract/request/ipType))             |
| `stealth_proxy`           | N/A, [ban avoidance](../../usage/errors.md#zapi-bans) is a transparent feature                                                                                                                                                                     |
| `own_proxy`               | Not supported                                                                                                                                                                                                                                      |
| `forward_headers`         | [customHttpRequestHeaders](https://docs.zyte.com/zyte-api/usage/reference.html#operation/extract/request/customHttpRequestHeaders), [requestHeaders](https://docs.zyte.com/zyte-api/usage/reference.html#operation/extract/request/requestHeaders) |
| `forward_headers_pure`    | Not supported                                                                                                                                                                                                                                      |
| `ai_query`                | [customAttributes](https://docs.zyte.com/zyte-api/usage/reference.html#operation/extract/request/customAttributes)                                                                                                                                 |
| `ai_selector`             | Not supported                                                                                                                                                                                                                                      |
| `ai_extract_rules`        | [customAttributes](https://docs.zyte.com/zyte-api/usage/reference.html#operation/extract/request/customAttributes)                                                                                                                                 |
| `extract_rules`           | Not supported                                                                                                                                                                                                                                      |
| `screenshot`              | [screenshot](https://docs.zyte.com/zyte-api/usage/reference.html#operation/extract/request/screenshot)                                                                                                                                             |
| `screenshot_selector`     | Not supported                                                                                                                                                                                                                                      |
| `screenshot_full_page`    | [screenshotOptions.fullPage=true](https://docs.zyte.com/zyte-api/usage/reference.html#operation/extract/request/screenshotOptions.fullPage)                                                                                                        |
| `json_response`           | See [Network capture](../../usage/browser.md#zapi-network-capture)                                                                                                                                                                                 |
| `return_page_source`      | Not supported (use [httpResponseBody](https://docs.zyte.com/zyte-api/usage/reference.html#operation/extract/request/httpResponseBody) if you are only using browser rendering to avoid bans)                                                       |
| `scraping_config`         | Not supported                                                                                                                                                                                                                                      |
| `session_id`              | [session.id](https://docs.zyte.com/zyte-api/usage/reference.html#operation/extract/request/session.id) (must be UUID4)                                                                                                                             |
| `timeout`                 | Not supported                                                                                                                                                                                                                                      |
| `cookies`                 | [requestCookies](https://docs.zyte.com/zyte-api/usage/reference.html#operation/extract/request/requestCookies)                                                                                                                                     |
| `device`                  | [device](https://docs.zyte.com/zyte-api/usage/reference.html#operation/extract/request/device)                                                                                                                                                     |
| `custom_google`           | N/A                                                                                                                                                                                                                                                |
| `transparent_status_code` | N/A, Zyte API returns the response or not based on whether or not it is a ban, not based on the status code                                                                                                                                        |

## Action mapping

ScrapingBee allows defining a sequence of browser actions through the
`"instructions"` JSON array of the `js_scenario` parameter. For example:

```json
{
    "instructions": [
        {"click": "#buttonId"}
    ]
}
```

Which URL-encoded would become:

```none
js_scenario=%7B%22instructions%22%3A+%5B%7B%22click%22%3A+%22%23buttonId%22%7D%5D%7D
```

The Zyte API equivalent is the [actions](https://docs.zyte.com/zyte-api/usage/reference.html#operation/extract/request/actions) field. The following is
a matching example:

```json
{
    "actions": [
        {
            "action": "click",
            "selector": {
                "type": "css",
                "value": "#buttonId"
            }
        }
    ]
}
```

These are ScrapingBee actions and their [Zyte API counterparts](../../usage/browser.md#zapi-actions):
`click`: `click`
`evaluate`: `evaluate`
`fill`: `type`
`infinite_scroll`: `scrollBottom`
`scroll_x`: `scrollTo`
`scroll_y`: `scrollTo`
`wait`: `waitForTimeout`
`wait_for`: `waitForSelector`
`wait_for_and_click`: `waitForSelector`, `click`
The following Zyte API actions are not supported by ScrapingBee:
`doubleClick`
`goto`
`hide`
`hover`
`keyPress`
`reload`
`searchKeyword`
`select`
`setLocation`
`waitForRequest`
`waitForResponse`

Zyte API also supports [custom actions](../../ide/index.md#zapi-scripts).
