# eSIMDB Travel eSIM Scraper (`rl1987/esimdb-scraper`) Actor

Scrapes travel eSIM data plans from esimdb.com, either a full crawl of all countries/regions or a targeted scrape of specific country/region URLs.

- **URL**: https://apify.com/rl1987/esimdb-scraper.md
- **Developed by:** [R.L.](https://apify.com/rl1987) (community)
- **Categories:** Travel, E-commerce
- **Stats:** 2 total users, 1 monthly users, 80.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 data plan rows

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

### What does eSIMDB Travel eSIM Scraper do?

**eSIMDB Travel eSIM Scraper** extracts travel eSIM data plans from [esimdb.com](https://esimdb.com), the largest independent travel eSIM comparison site, covering 400,000+ prepaid plans from 200+ providers. It talks directly to the same JSON endpoints the site itself uses to render its country and region pages, so results come back fast and complete — no browser rendering or pagination clicking required. Run it on the [Apify platform](https://apify.com) to get scheduled runs, API access, and integrations with Zapier, Make, Google Sheets, and more.

### Why use eSIMDB Travel eSIM Scraper?

- **Price monitoring** — track how travel eSIM prices for a country or region change over time.
- **Market research** — compare data caps, validity periods, and pricing across every provider selling eSIMs for a destination.
- **Affiliate/comparison sites** — power your own eSIM comparison tool with structured, up-to-date plan data.
- **Competitor analysis** — see exactly which plans a competing provider offers and at what price.

### How to use eSIMDB Travel eSIM Scraper

1. Click **Try for free** or **Run** on the Apify platform.
2. Choose a **Scrape mode**:
   - **Full crawl** — scrapes every country and region eSIMDB tracks (default). ⚠️ **This is hundreds of thousands of unique plans**, and at $1 per 1000 rows the bill scales accordingly. Before starting it, raise the run's **Max total charge** above the platform default, or the run will stop early once that cap is hit — the Actor logs its own row/cost estimate as soon as it starts.
   - **Targeted** — scrapes only the country/region URLs you provide, and is far cheaper.
3. If using Targeted mode, add one or more eSIMDB country or region page URLs, e.g. `https://esimdb.com/france` or `https://esimdb.com/region/europe`.
4. Click **Start** and wait for the run to finish.
5. Download your results from the **Storage** tab in JSON, CSV, Excel, or other formats.

### Input

| Field | Type | Description |
|---|---|---|
| `mode` | String | `full` or `targeted`. |
| `startUrls` | Array | Country/region page URLs to scrape (targeted mode only). |
| `proxyConfiguration` | Object | Optional proxy settings, useful if eSIMDB starts rate-limiting your IP. |
| `includeAffiliateLinks` | Boolean | Fetch each provider's website/App Store/Google Play affiliate links (default: `true`). |
| `maxConcurrency` | Integer | Max parallel requests (default: 10). |
| `requestDelaySecs` | Number | Politeness delay between requests, in seconds (default: 0.3). |

See the **Input** tab for the full schema.

### Output

Each dataset item is one **unique** data plan. Plans sold across multiple countries or regions (e.g. a pan-European bundle) are listed identically under every destination on eSIMDB's own site — this Actor deduplicates those by plan ID across the whole run and instead lists everywhere that plan is sold in `coverageCountries`/`coverageRegions`, so you're not billed once per country for the same plan. Example:

```json
{
    "planId": "6a3a519761cac50f90a944d6",
    "planName": "10GB / 7 Days",
    "validityInfo": "",
    "dataCapacityMb": 10000,
    "isUnlimited": false,
    "validityDays": 7,
    "prices": { "USD": 8, "EUR": 8, "GBP": 7 },
    "usdPrice": 8,
    "has5G": true,
    "isLowLatency": true,
    "providerName": "Ubigi",
    "providerSlug": "ubigi",
    "providerWebsiteUrl": "https://go.ubigi.com/Jz5GLE",
    "providerAppStoreUrl": null,
    "providerPlayStoreUrl": null,
    "coverageCountries": ["France"],
    "coverageRegions": [],
    "planUrl": "https://esimdb.com/france/ubigi"
}
```

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

#### Data table

| Field | Description |
|---|---|
| `planName` / `planId` | Plan name and unique ID |
| `dataCapacityMb`, `isUnlimited` | Data allowance (0 + `isUnlimited: true` means unlimited/speed-capped) |
| `validityDays`, `validityInfo` | How long the plan lasts |
| `prices`, `usdPrice`, `promoPrices`, `usdPromoPrice` | Pricing in listed currencies and USD |
| `has5G`, `isLowLatency`, `tethering`, `telephony` | Plan capabilities |
| `providerName`, `providerSlug`, `providerCertified` | The eSIM provider selling the plan |
| `providerWebsiteUrl`, `providerAppStoreUrl`, `providerPlayStoreUrl` | The provider's affiliate links, when eSIMDB has them |
| `coverageCountries` | Every country this plan is sold under, as human-readable names |
| `coverageRegions` | Every region this plan is sold under, as `{slug, name}` pairs |
| `planUrl` | Link to this plan's page on eSIMDB (first listed country, or region if it's region-only) |

### Cost estimation

This Actor bills **$1.00 per 1000 dataset rows** (pay-per-event), not per compute unit — so cost scales with how many *unique* plans end up in your dataset, not how long the run takes or how many countries it touches. Plans sold in multiple countries are billed once, not once per country (see Output above).

- **Targeted mode**: cost is exactly `(unique plans returned / 1000) * $1`. Scraping one mid-size country alone (e.g. ~13,000 raw listings) costs less than that once shared multi-country plans are deduplicated against whatever else you're scraping in the same run.
- **Full crawl**: eSIMDB advertises 400,000+ plans site-wide, so a full crawl's bill is in that ballpark — the actual number depends on eSIMDB's current catalog. The raw per-country/region listing count (before dedup) is several times larger than that; the Actor logs both the raw listing estimate at startup and the real deduplicated row count once fetching finishes, so check those log lines rather than assuming a fixed number.

**Before running a full crawl, raise the run's "Max total charge" (`maxTotalChargeUsd`) setting** above the platform default — otherwise the run will stop early once that spending cap is hit, leaving you with a partial (but still billed) dataset. Compute-unit cost on top of that is low, since this Actor only makes lightweight HTTP requests (no browser rendering).

Because deduplication needs to see every scraped target before it knows which plans overlap, results are buffered in memory and pushed to the dataset in batches near the end of the run rather than streamed continuously — you won't see dataset items appear until fetching finishes.

### Tips

- Use **Targeted** mode with a small `startUrls` list when you only care about a handful of destinations — it's both faster and dramatically cheaper than a full crawl.
- Before a full crawl, check the Actor's startup log for its row/cost estimate and set a **Max total charge** on the run that covers it, or the run will stop early.
- Turn off `includeAffiliateLinks` if you don't need provider website/app-store links — it skips the extra per-provider page fetches (this doesn't affect the per-row price, only compute time).
- Increase `maxConcurrency` for faster full crawls if eSIMDB isn't rate-limiting you; lower it (and raise `requestDelaySecs`) if you see request failures.
- Enable `proxyConfiguration` if you start seeing failed requests due to IP-based rate limiting.

### FAQ, disclaimers, and support

This Actor scrapes publicly available data from esimdb.com and respects its `robots.txt`. It is provided for research and comparison purposes; review eSIMDB's [Terms of Use](https://esimdb.com/terms) before large-scale or commercial use. Found a bug or want a custom version of this Actor? Open an issue in the Actor's **Issues** tab.

# Actor input Schema

## `mode` (type: `string`):

"Full crawl" scrapes every country and region on eSIMDB — that's well over a million rows, and at $1 per 1000 rows this run's bill scales accordingly. Before running it, raise this run's "Max total charge" (maxTotalChargeUsd) above the default, or the run will stop early once that cap is hit; the Actor logs its own row/cost estimate at startup. "Targeted" only scrapes the country/region URLs listed below and is far cheaper.

## `startUrls` (type: `array`):

eSIMDB country or region page URLs to scrape, e.g. https://esimdb.com/france or https://esimdb.com/region/europe. Only used when mode is "targeted".

## `proxyConfiguration` (type: `object`):

Proxy to route requests through. eSIMDB blocks direct requests from Apify's datacenter IPs (403 Forbidden), so Apify Proxy is on by default.

## `includeAffiliateLinks` (type: `boolean`):

Fetch each provider's website/App Store/Google Play affiliate links and add them to every plan. Adds one extra request per unique provider (cached across the run), so it costs more but is on by default.

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

Maximum number of country/region/provider requests to run in parallel.

## `requestDelaySecs` (type: `number`):

Politeness delay applied after each request, per concurrent worker.

## Actor input object example

```json
{
  "mode": "targeted",
  "startUrls": [
    {
      "url": "https://esimdb.com/france"
    }
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "includeAffiliateLinks": true,
  "maxConcurrency": 10,
  "requestDelaySecs": 0.3
}
```

# Actor output Schema

## `dataset` (type: `string`):

Deduplicated eSIM data plans scraped from esimdb.com.

# 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 = {
    "startUrls": [
        {
            "url": "https://esimdb.com/france"
        }
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("rl1987/esimdb-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 = {
    "startUrls": [{ "url": "https://esimdb.com/france" }],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("rl1987/esimdb-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 '{
  "startUrls": [
    {
      "url": "https://esimdb.com/france"
    }
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call rl1987/esimdb-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,rl1987/esimdb-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/nJvWd2RksNWsfd0YF/builds/bIhsZEFhFsF1GIxI6/openapi.json
