# Protected Website Scraper (`stealthasf/protected-website-scraper`) Actor

Get the HTML or structured data of pages behind Cloudflare, DataDome, Akamai, PerimeterX and Kasada. Runs through the StealthASF API with your own key; blocked requests are not charged.

- **URL**: https://apify.com/stealthasf/protected-website-scraper.md
- **Developed by:** [Žygimantas Vičkačka](https://apify.com/stealthasf) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-usage

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Protected Website Scraper (Cloudflare, DataDome, Akamai, PerimeterX, Kasada)

Give it a list of URLs and get back the page HTML or clean structured data, including from sites behind Cloudflare, DataDome, Akamai, PerimeterX and Kasada. Each URL becomes one row in the dataset, with the site's HTTP status, the engine that fetched it, and the credits it cost.

The Actor runs your requests through the [StealthASF](https://stealthasf.com) scraping API. You do not need an Apify proxy, browser settings or captcha setup. Blocked requests are not charged.

### Tested on real protected sites

On 2026-10-08 our production tests returned real pages for:

| Protection | Sites |
| --- | --- |
| PerimeterX | Zillow, Walmart, StockX |
| Akamai | Nike, Lowe's, Home Depot |
| DataDome | Tripadvisor, Allegro |
| Cloudflare | Glassdoor, WhoScored |
| Kasada | Hyatt, realestate.com.au |

### What you need

A StealthASF API key. Sign up at [stealthasf.com](https://stealthasf.com): you get **200 free credits, no card needed**. Copy your key from the [dashboard](https://stealthasf.com/dashboard) and paste it into the **StealthASF API key** field. The key is stored encrypted by Apify.

### How to use it

1. Paste your API key.
2. Add the URLs you want, one per line, or upload a text file with one URL per line.
3. Leave **Engine** on **Auto** unless you know the site needs a specific mode.
4. Pick an **Extract** option if you want structured data instead of raw HTML.
5. Start the run and download the results as JSON, CSV, Excel or HTML from the Output tab.

#### Engines

| Engine | What it does | Base credits |
| --- | --- | --- |
| `auto` (default) | Starts with a plain request and steps up to protected mode only when the site blocks it. Remembers sites that needed protected mode. You pay only for the engine that succeeded. | depends on the result |
| `http` | Plain HTTP request | 1 |
| `browser` | Renders JavaScript | 5 |
| `stealth` | Protected request for anti-bot sites | 25 |
| `ultra` | Our strongest mode, for the hardest protected sites | 50 |

Use `browser` when a page loads its content with JavaScript and `auto` returns an empty page shell.

#### Extract options

| Value | Returns in `data` |
| --- | --- |
| `none` | Nothing extra; use `includeHtml` to get the page |
| `links` | Every link with its text |
| `text` | Clean readable page text |
| `meta` | Title, description and Open Graph tags |
| `images` | Image URLs with alt text |
| `headings` | H1 to H3 outline |
| `table` | The first data table on the page |

### Input example

```json
{
    "apiKey": "YOUR_STEALTHASF_API_KEY",
    "urls": [
        { "url": "https://www.example.com/" },
        { "url": "https://www.example.com/products" }
    ],
    "engine": "auto",
    "extract": "meta",
    "includeHtml": false,
    "maxConcurrency": 3
}
```

| Field | Type | Default | Notes |
| --- | --- | --- | --- |
| `apiKey` | string | required | Your StealthASF API key |
| `urls` | array | required | URLs, or a link to a text file with one URL per line |
| `engine` | string | `auto` | `auto`, `http`, `browser`, `stealth`, `ultra` |
| `extract` | string | `none` | `none`, `links`, `text`, `meta`, `images`, `headings`, `table` |
| `country` | string | empty | Two-letter country code such as `US` or `de`. Pro and Scale plans |
| `includeHtml` | boolean | `false` | Store the full HTML in each row |
| `maxConcurrency` | integer | `3` | 1 to 20 URLs at a time |

### Output example

One dataset item per URL:

```json
{
    "url": "https://www.example.com/",
    "ok": true,
    "status": 200,
    "engine": "http",
    "creditsCharged": 1,
    "jobId": "cm2x8k1q40001",
    "data": {
        "kind": "table",
        "columns": ["field", "value"],
        "rows": [["title", "Example Domain"]]
    },
    "error": null
}
```

| Field | Meaning |
| --- | --- |
| `url` | The URL you asked for |
| `ok` | `true` when the page was fetched |
| `status` | The site's own HTTP status (for example 200 or 404) |
| `engine` | The engine that produced the result |
| `creditsCharged` | Credits this URL cost; `0` when it was blocked or rejected |
| `jobId` | The job ID, also visible in your StealthASF dashboard |
| `data` | Structured result when `extract` is set |
| `html` | Full page HTML, only when `includeHtml` is on |
| `error` | What went wrong, when `ok` is `false` |

A page the site blocked looks like this and costs nothing:

```json
{
    "url": "https://www.example.com/",
    "ok": false,
    "status": null,
    "engine": null,
    "creditsCharged": 0,
    "jobId": "cm2x8k1q40002",
    "data": null,
    "error": "HTTP 422: blocked by the target's anti-bot protection (not charged)"
}
```

At the end of the run the log and the run status show a summary: pages fetched, pages blocked, credits used and the balance left on your account.

### Credits and pricing

Credits come from your StealthASF account. Apify bills only its normal platform usage for the run, which stays low because the Actor only sends API requests and waits for the answers.

| What | Credits |
| --- | --- |
| HTTP request | 1 (+1 per 2 MB of response) |
| Browser request | 5 |
| Stealth request | 25 |
| Ultra request | 50 |
| Transfer beyond the first MB (browser, stealth, ultra) | +10 per MB |
| Blocked request | 0 |

Every row shows the exact `creditsCharged`, so you always see what each page cost.

**Plans start at $17/month, and one-time credit packs start at $12.** See [stealthasf.com](https://stealthasf.com) for all plans.

### Good to know

- **Out of credits:** the run stops with a clear message and keeps every row already saved. Top up and run again.
- **Invalid API key:** the run stops at the first rejected request instead of repeating the same error for every URL.
- **Concurrency:** each StealthASF plan has its own limit of parallel requests. If `maxConcurrency` is higher, the Actor lowers it to your plan's limit automatically and retries. Requests over the limit are never charged.
- **Rate limits:** when the API asks the Actor to slow down, it waits and retries up to 3 times.
- **Large pages:** a page bigger than the Apify dataset item limit keeps its row and `data`, but `html` is left out. Use an `extract` option for those pages.

### Use it from code

The Actor works with the Apify API, scheduler, webhooks and integrations like any other Actor. If you would rather call the scraping API directly from your own code, the same features are available at [stealthasf.com](https://stealthasf.com).

# Actor input Schema

## `apiKey` (type: `string`):

Your API key from <a href="https://stealthasf.com/dashboard" target="_blank">stealthasf.com/dashboard</a>. New accounts get 200 free credits, no card needed. Stored encrypted. Required to scrape; without it the run only returns instructions.

## `urls` (type: `array`):

Pages to fetch. Each URL is one request and one dataset item. You can also upload a file or link to a text file with one URL per line.

## `engine` (type: `string`):

<b>auto</b> starts with a plain request and steps up to protected mode only when a block is detected; you pay for the tier that succeeded. <b>http</b>: plain request (1 credit). <b>browser</b>: JavaScript rendering (5). <b>stealth</b>: protected request (25). <b>ultra</b>: strongest mode for the hardest sites (50).

## `extract` (type: `string`):

Return structured data in the <code>data</code> field instead of parsing HTML yourself.

## `country` (type: `string`):

Optional two-letter country code (ISO 3166-1 alpha-2, for example US or de) to fetch the page from that country. Available on the StealthASF Pro and Scale plans.

## `includeHtml` (type: `boolean`):

Store the full page HTML in each dataset item. Leave off when you only need the extracted data.

## `maxConcurrency` (type: `integer`):

How many URLs to fetch at the same time. Your StealthASF plan has its own concurrency limit; requests over it are retried and never charged.

## Actor input object example

```json
{
  "urls": [
    {
      "url": "https://example.com/"
    }
  ],
  "engine": "auto",
  "extract": "none",
  "includeHtml": false,
  "maxConcurrency": 3
}
```

# Actor output Schema

## `results` (type: `string`):

One item per URL: url, ok, status, engine, creditsCharged, jobId, data, html (when requested) and error.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "urls": [
        {
            "url": "https://example.com/"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("stealthasf/protected-website-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "urls": [{ "url": "https://example.com/" }] }

# Run the Actor and wait for it to finish
run = client.actor("stealthasf/protected-website-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "urls": [
    {
      "url": "https://example.com/"
    }
  ]
}' |
apify call stealthasf/protected-website-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,stealthasf/protected-website-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/afX1DQmAhGdhIrfff/builds/qIw7fqiAoft4kD2Wd/openapi.json
