# Website Block Checker: Datacenter vs Real Mobile IP (`xavierfok/website-block-checker`) Actor

Find out whether a website blocks scrapers by IP type. Each URL is loaded from a datacenter IP and from a real Singapore 4G mobile IP, and you get which one was blocked or challenged (Cloudflare, Akamai, PerimeterX, DataDome, AWS WAF, Google, Reddit...).

- **URL**: https://apify.com/xavierfok/website-block-checker.md
- **Developed by:** [Xavier Fok](https://apify.com/xavierfok) (community)
- **Categories:** Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 url checkeds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

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

## Website Block Checker: Datacenter vs Real Mobile IP

Before you build a scraper, find out what you're up against. Give it a list of URLs and each one is loaded twice:

1. from a **datacenter IP** (a cloud server, like most scrapers run from), and
2. from a **real Singapore mobile IP** (a physical 4G modem with a Singtel or M1 SIM card).

You get back which side was blocked or challenged, by whom, and a plain-English verdict. Useful for:

- deciding whether a target needs residential/mobile proxies or whether cheap datacenter IPs will do
- debugging a scraper that suddenly gets 403s: is it your code, or your IP?
- checking whether a site shows different content to different kinds of visitors

### Verdicts

| Verdict | Meaning |
|---|---|
| `blocks_datacenter` | Refuses or challenges the datacenter IP, serves the mobile IP. You need better IPs. |
| `harder_on_datacenter` | Hard-blocks the datacenter IP, but only shows the mobile IP a JS challenge a real browser can usually pass. Better IPs plus a browser will get through. Reddit behaves like this. |
| `blocks_both` | Blocks both. IP quality alone won't fix it; you likely need a real browser (JS challenge) or a different approach. |
| `blocks_mobile` | Rare, but it happens (some sites rate-limit carrier-grade NAT ranges). |
| `soft_block_datacenter_suspected` | Both loaded, but the datacenter page was much smaller (a stripped or placeholder page is a common quiet block). |
| `open` | Loads from both. Datacenter proxies are probably fine. |
| `open_regional_redirect` | Loads from both, but each side was sent to a different regional site (e.g. amazon.com vs amazon.sg), so the pages aren't directly comparable. |
| `inconclusive` / `error` | One or both sides couldn't connect. Not charged when both fail. |
| `rejected` | The URL isn't a public website (see limits below). Not charged. |

Detected blockers include Cloudflare (challenge and 1020 blocks), Akamai, PerimeterX / HUMAN, DataDome, AWS WAF, Imperva, Google's "unusual traffic" page, Reddit's network wall, and plain 403/429 refusals.

### Input

```json
{
  "urls": [
    "https://www.reddit.com/r/python/",
    "https://www.example-shop.com/category/shoes"
  ]
}
```

### Output

One row per URL:

```json
{
  "url": "https://www.reddit.com/r/python/",
  "verdict": "harder_on_datacenter",
  "summary": "Hard-blocks datacenter IPs (reddit); shows the mobile IP a challenge a real browser can usually pass.",
  "datacenter": {
    "ok": true,
    "status": 403,
    "final_url": "https://www.reddit.com/r/python/",
    "redirects": 0,
    "title": null,
    "bytes": 190240,
    "ms": 16,
    "blocked": true,
    "block_vendor": "reddit",
    "block_kind": "denied",
    "exit": {
      "ok": true,
      "ip": "32.198.x.x",
      "country": "US",
      "asn": 14618,
      "network": "Amazon.com, Inc."
    }
  },
  "mobile": {
    "ok": true,
    "status": 200,
    "final_url": "https://www.reddit.com/r/python/",
    "redirects": 0,
    "title": "Reddit - Prove your humanity",
    "bytes": 166958,
    "ms": 3894,
    "blocked": true,
    "block_vendor": "reddit",
    "block_kind": "challenge",
    "exit": {
      "ok": true,
      "ip": "111.65.x.x",
      "country": "SG",
      "asn": 45143,
      "network": "Singapore Telecom Mobile Pte Ltd"
    }
  },
  "region_note": null,
  "input_index": 0
}
```

We never return page content, only status, title, size, timing and the block diagnosis.

### Good to know

- **Most sites don't block by IP alone.** In our own tests on popular sites (Google, Amazon, Lazada, Walmart, Zillow), plain requests got through from both kinds of IP. That's useful to know too: if a site comes back `open`, don't pay for premium proxies you don't need.
- **Location differs too.** The datacenter side runs in Apify's cloud (usually the US); the mobile side is in Singapore. Some sites redirect by region, and `region_note` flags that when it happens.
- **One request per side, no JavaScript.** Requests use a real Chrome TLS fingerprint, but no browser runs. A JS challenge counts as "challenged", even though a real browser might pass it.
- **Limits:** up to 20 URLs per run, standard ports (80/443) only, public websites only. Internal or private addresses, URLs with credentials, and our own infrastructure are refused, including after redirects.

### The mobile IP behind this actor

The mobile side runs on a dedicated line from [Singapore Mobile Proxy](https://singaporemobileproxy.com/?utm_source=apify\&utm_medium=marketplace\&utm_campaign=block_checker): real Singapore SIM cards (Singtel, M1) in physical modems, with IP rotation on demand from a link. If your target comes back `blocks_datacenter`, that's the kind of line that gets through. Code **APIFY15** takes 15% off your first payment.

Want to check proxies you already have? See our [Proxy Checker](https://apify.com/xavierfok/proxy-quality-checker).

### Data attribution

IP to ASN and country data: [DB-IP Lite](https://db-ip.com), licensed CC BY 4.0.

# Actor input Schema

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

Up to 20 public http(s) URLs. Each is loaded once from a datacenter IP and once from a real Singapore mobile IP. Private/internal addresses and non-standard ports are refused.

## `timeoutSecs` (type: `integer`):

Per-request timeout for each side.

## Actor input object example

```json
{
  "urls": [
    "https://www.reddit.com/r/python/",
    "https://www.google.com/search?q=weather",
    "https://www.amazon.com/s?k=usb+cable"
  ],
  "timeoutSecs": 20
}
```

# Actor output Schema

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

Every URL checked, in the overview table view.

## `allFields` (type: `string`):

Full rows with both sides' details, redirects and region notes.

# 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": [
        "https://www.reddit.com/r/python/",
        "https://www.google.com/search?q=weather",
        "https://www.amazon.com/s?k=usb+cable"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("xavierfok/website-block-checker").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": [
        "https://www.reddit.com/r/python/",
        "https://www.google.com/search?q=weather",
        "https://www.amazon.com/s?k=usb+cable",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("xavierfok/website-block-checker").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": [
    "https://www.reddit.com/r/python/",
    "https://www.google.com/search?q=weather",
    "https://www.amazon.com/s?k=usb+cable"
  ]
}' |
apify call xavierfok/website-block-checker --silent --output-dataset

```

## MCP server setup

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

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/0hzMe5U5dRJFW2Dy0/builds/XZoIAuD9eKXZng238/openapi.json
