# eSIMDB Country Scraper (`codingfrontend/esimdb-country-scraper`) Actor

Extract public eSIM plan cards from eSIMDB country pages, including provider, plan, allowance, validity, and price metadata.

- **URL**: https://apify.com/codingfrontend/esimdb-country-scraper.md
- **Developed by:** [Coding Frontned](https://apify.com/codingfrontend) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.99 / 1,000 results

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

### What does eSIMDB Country Scraper do?

Collect **public eSIM plan comparison rows** from [eSIMDB](https://esimdb.com/france) country pages. Results include the country, provider, plan name, displayed data allowance, validity, price, currency and price per GB when the source publishes them. Unlimited data after a speed reduction is preserved as part of the displayed allowance.

Use the dataset for travel-connectivity research, plan comparison or a dashboard. You can run the Actor from Apify Console, schedule snapshots and export genuine plan records to your existing tools. The Actor collects the plans actually present in each public page response; it does not promise the publisher's entire catalogue or plans loaded later by interactive controls.

### How to use it

1. Open the Input tab and add public country pages such as France or India.
2. Choose a small plan limit for your first run.
3. Start the Actor and inspect the plan table in Output.
4. Download the results as JSON, CSV or Excel. Read the run summary if a source page was unavailable.

### Input example

```json
{"startUrls":["https://esimdb.com/france"],"maxPlans":20}
```

The default source is France and the default limit is 50 plans. `startUrls` accepts up to 20 country pages; the limit applies across all of them. `timeoutSecs` defaults to 30 seconds per request and `maxResponseBytes` defaults to five million bytes. The Input tab keeps these existing controls and limits. One bounded retry is used for transient server/network failures. Access restrictions and rate limits stop further source requests.

Multiple variants can share one provider page and plan name. `recordId` uses a matched public source plan identifier when available. If that metadata cannot be matched, the identity is derived from the country, provider, label, allowance, validity and displayed price; that fallback can change after a price update. Repeated copies of the same identified plan are suppressed. A displayed zero price remains zero, and missing price-per-GB information is omitted rather than filled with a placeholder.

### Real output example

This record was saved by the actual local Actor on 6 October 2026. It comes from the public France page; provider, plan terms and prices were read from the source, not invented. Prices and availability can change after collection.

```json
{
  "recordType": "plan",
  "recordId": "esimdb:france:6ab39fdc196bc160cf5b892f",
  "countryName": "France",
  "countrySlug": "france",
  "provider": "Horizon eSIM",
  "planName": "France 100MB 7Days",
  "dataAmount": "100MB",
  "validity": "7 Days",
  "price": "$0.26",
  "currency": "USD",
  "pricePerGb": "$2.58/GB",
  "planUrl": "https://esimdb.com/france/horizonesim",
  "sourceUrl": "https://esimdb.com/france",
  "sourceDomain": "esimdb.com",
  "extractionMethod": "html-plan-card",
  "transport": "direct-public-http",
  "scrapedAt": "2026-10-06T08:39:10.167Z"
}
```

| Fields | Meaning |
|---|---|
| `countryName`, `countrySlug` | Source country and public route |
| `provider`, `planName` | Published provider and plan label |
| `dataAmount` | Displayed allowance, including published throttling terms |
| `validity` | Displayed validity or no-expiry wording |
| `price`, `currency`, `pricePerGb` | Displayed price and available comparison figures |
| `planUrl`, `sourceUrl` | Provider/plan page and country page |
| `recordId`, `scrapedAt` | Variant identity and UTC collection time |

Prices remain displayed strings; the Actor does not invent currency conversions or change monetary units. Advertised data and validity remain the source's wording. Country-page rows sometimes link to a provider page shared by several plans, so a link alone is not a unique plan identity.

### Run results and costs

A run with useful saved plans succeeds even when a later country page fails. The summary marks partial collection and reports actual saved counts and source issues. A run with zero useful plans fails. Customer datasets contain plan rows; error-only records and raw page dumps are not added as results.

Review the price and resource settings shown in Apify Console before starting. Larger limits and additional country pages can increase platform usage. Start small and increase the limit according to the amount of publicly available data you need.

### Limits and support

Only publicly readable eSIMDB pages are requested. The Actor does not open checkout flows, submit purchases or follow external provider sites. Page markup can change, and not every country page contains every plan in the publisher's live catalogue. The existing maximum is a cap, not a guaranteed number of records.

Use the Actor's Issues tab with the input and run link if the source page is readable but the output looks incomplete. Check the timestamp and advertised terms before relying on a historical comparison.

# Actor input Schema

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

Public eSIMDB country URLs such as https://esimdb.com/france.

## `maxPlans` (type: `integer`):

Maximum unique eSIM plan cards across the requested country pages.

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

Maximum time to wait for each country page.

## `maxResponseBytes` (type: `integer`):

Bound the HTML response size before parsing.

## Actor input object example

```json
{
  "startUrls": [
    "https://esimdb.com/france"
  ],
  "maxPlans": 50,
  "timeoutSecs": 30,
  "maxResponseBytes": 5000000
}
```

# Actor output Schema

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

Dataset containing public-source records.

## `keyValueStore` (type: `string`):

Key-value store containing the OUTPUT run summary.

# 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": [
        "https://esimdb.com/france"
    ],
    "maxPlans": 50,
    "timeoutSecs": 30,
    "maxResponseBytes": 5000000
};

// Run the Actor and wait for it to finish
const run = await client.actor("codingfrontend/esimdb-country-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": ["https://esimdb.com/france"],
    "maxPlans": 50,
    "timeoutSecs": 30,
    "maxResponseBytes": 5000000,
}

# Run the Actor and wait for it to finish
run = client.actor("codingfrontend/esimdb-country-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": [
    "https://esimdb.com/france"
  ],
  "maxPlans": 50,
  "timeoutSecs": 30,
  "maxResponseBytes": 5000000
}' |
apify call codingfrontend/esimdb-country-scraper --silent --output-dataset

```

## MCP server setup

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