# eMAG Product Scraper — Romania, Bulgaria, Hungary (`polyglot-data/emag-product-scraper`) Actor

Scrape eMAG.ro, eMAG.bg and eMAG.hu: prices, discounts, ratings, reviews, stock, brand, seller and category. Residential proxy built in, 60 products per request, pay per result.

- **URL**: https://apify.com/polyglot-data/emag-product-scraper.md
- **Developed by:** [Polyglot Data](https://apify.com/polyglot-data) (community)
- **Categories:** E-commerce
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 product scrapeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## eMAG Product Scraper — Romania, Bulgaria, Hungary

Extract product data from **eMAG**, the largest online marketplace in Central and Eastern Europe:
**emag.ro** 🇷🇴, **emag.bg** 🇧🇬 and **emag.hu** 🇭🇺.

Get prices, discounts, ratings, reviews, stock, brand, seller and category for any search, category or product
URL. The output is clean, flat JSON that you can export to Excel, CSV or Google Sheets, or pull from the API.

***

### ✅ Why this scraper

- **Works where others fail.** eMAG blocks datacenter IPs. This actor uses residential IPs from the site's own country by default, detects blocked pages and retries them with a fresh session.
- **Tested on all three sites.** Every field is checked against live emag.ro, emag.bg and emag.hu pages, including local labels in Romanian, Bulgarian and Hungarian.
- **Fast and cheap.** It uses plain HTTP requests with no browser. Fast mode reads **60 products per request**.
- **Pay per result.** The per-result fee is charged only for products actually saved, never for failed or empty pages.
- **Clean data.** Prices are numbers, not strings ("1.299,99 Lei" → `1299.99`), with an ISO currency code. Missing values are `null`, never empty strings.
- **Maintained.** If eMAG changes its layout, the selectors get updated. Report anything odd in the **Issues** tab.

***

### 📦 What data you get

| Field | Example | Notes |
|---|---|---|
| `url` | `https://www.emag.ro/.../pd/D5XXXXXBM/` | Product page |
| `productId` | `D5XXXXXBM` | eMAG product code |
| `title` | `Telefon mobil Nokia 105 (2024), Dual SIM, Black` | |
| `brand` | `Nokia` | Detail mode |
| `price` | `90.75` | Current price, number |
| `currency` | `RON` | RON (Romania), EUR (Bulgaria, since 2026) or HUF (Hungary) |
| `oldPrice` | `96.80` | Previous price (lowest of the last 30 days), only when discounted |
| `discountPct` | `6` | Computed from `price` and `oldPrice` |
| `rating` | `4.12` | 0–5 |
| `reviewCount` | `17` | |
| `inStock` | `true` | |
| `seller` | `eMAG` | eMAG or the marketplace seller. Detail mode |
| `imageUrl` | `https://s13emagst.akamaized.net/...jpg` | Main image |
| `category` | `Telefoane mobile` | From the breadcrumb. Detail mode |
| `country` | `ro` | Site the product came from |
| `scrapedAt` | `2026-10-09T18:30:00.000Z` | UTC timestamp |

#### Example item

```json
{
  "url": "https://www.emag.ro/telefon-mobil-nokia-105-2024-dual-sim-black/pd/D5XXXXXBM/",
  "productId": "D5XXXXXBM",
  "title": "Telefon mobil Nokia 105 (2024), Dual SIM, Black",
  "brand": "Nokia",
  "price": 90.75,
  "currency": "RON",
  "oldPrice": 96.8,
  "discountPct": 6,
  "rating": 4.12,
  "reviewCount": 17,
  "inStock": true,
  "seller": "eMAG",
  "imageUrl": "https://s13emagst.akamaized.net/products/example.jpg",
  "category": "Telefoane mobile",
  "country": "ro",
  "scrapedAt": "2026-10-09T18:30:00.000Z"
}
```

#### ⚠️ Error items

If an input produces nothing, the actor saves an error item instead of failing silently. Error items are **never charged**.

```json
{ "error": "NO_RESULTS", "note": "No products found for this input. Check the search term, URL and country.", "input": ["xyzabc"] }
```

| error | Meaning |
|---|---|
| `NO_RESULTS` | The search or category returned no products |
| `NOT_FOUND` | The URL does not exist on eMAG |
| `BLOCKED` | eMAG refused the page after all retries (rare; try again later) |

***

### 🎯 Use cases

- **Price monitoring:** schedule a daily run and track price changes and discounts over time.
- **Competitor analysis:** see what competing sellers charge for the same products on eMAG Marketplace.
- **Seller research:** find which marketplace sellers dominate a category.
- **Brand protection and MAP compliance:** check how resellers price your brand in RO, BG and HU.
- **Market research:** compare assortment, ratings and prices across three countries.
- **Repricing tools and BI dashboards:** feed fresh prices into your own systems through the API.

***

### ⚡ Fast mode vs. detail mode

| | Fast mode (default) | Detail mode (`scrapeDetails: true`) |
|---|---|---|
| How it works | Reads search and category pages only | Also opens every product page |
| Speed | 60 products per request | 1 request per product |
| url, productId, title, price, currency, imageUrl | ✅ | ✅ |
| oldPrice, discountPct (discounted products) | ✅ | ✅ |
| rating, reviewCount | ✅ | ✅ |
| inStock | ✅ when shown on the card | ✅ |
| brand, seller, category | — | ✅ |
| Platform usage, measured Oct 2026 | ≈ $0.01 per 1,000 products | ≈ $0.50–0.70 per 1,000 products |

**Tip:** use fast mode for daily price tracking and detail mode when you need the seller or brand.

***

### 🚀 How to use

1. Enter one or more **search terms** (for example `iphone 15`) or paste **eMAG URLs** (search, category or product pages).
2. Pick the **country** site for your search terms and set **Max items**.
3. Click **Start**, then download the results as JSON, CSV, Excel or HTML, or connect them to Google Sheets.

#### Input example: fast price monitoring

```json
{
  "searchTerms": ["laptop gaming", "casti wireless"],
  "country": "ro",
  "maxItems": 500
}
```

#### Input example: full product details

```json
{
  "startUrls": [{ "url": "https://www.emag.bg/mobilni-telefoni/c" }],
  "maxItems": 100,
  "scrapeDetails": true
}
```

#### Input fields

| Field | Type | Default | Description |
|---|---|---|---|
| `searchTerms` | string\[] | `[]` | Terms to search for on the selected site. |
| `startUrls` | request list | `[]` | Search, category or product URLs on emag.ro / emag.bg / emag.hu. URLs containing `/pd/` are scraped as product pages. |
| `country` | `ro` / `bg` / `hu` | `ro` | Site used for `searchTerms`. |
| `maxItems` | integer | `100` | Maximum number of products to save. |
| `scrapeDetails` | boolean | `false` | Open every product page to also get brand, seller, stock and category. |
| `proxyConfiguration` | proxy object | Apify residential | eMAG blocks datacenter IPs, so residential is required. The proxy country is set to the site's country automatically. |
| `debug` | boolean | `false` | Adds page diagnostics to the dataset, for troubleshooting. |

***

### 🔌 Integrations and API

- **Schedules:** run it every day or every hour from the Schedules tab.
- **Webhooks, Make, Zapier, n8n, Google Sheets:** send results anywhere when a run finishes.
- **API:** start a run and get the items in one call:

```bash
curl -X POST "https://api.apify.com/v2/acts/Polyglot-Data~emag-product-scraper/run-sync-get-dataset-items?token=YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"searchTerms":["iphone 15"],"country":"ro","maxItems":50}'
```

***

### 💰 Pricing

**Pay per result:** you pay a small fixed price for each product saved to the dataset (see the **Pricing** tab),
plus Apify platform usage (see the table above). There is no monthly rental, and the per-result fee is never charged for empty or failed pages.
A test run with `maxItems: 20` costs a few cents.

***

### ❓ FAQ

**Which sites are supported?**
emag.ro (Romania), emag.bg (Bulgaria) and emag.hu (Hungary).

**Do I need my own proxies?**
No. The actor uses Apify residential proxy from the matching country by default.

**Why is `oldPrice` often `null`?**
eMAG only shows a previous price (the lowest price of the last 30 days) on discounted products.

**Why are `brand`, `seller` and `category` empty?**
eMAG does not show them on search pages. Turn on `scrapeDetails` to get them.

**What happens when eMAG blocks a request?**
The actor detects the block (HTTP 403/429/511 or a captcha page), drops that session and retries with a new IP, up to 8 times.

**Can I scrape a whole category?**
Yes. Paste the category URL into `startUrls` and raise `maxItems`. The actor follows pagination automatically.

**Something is broken or a field is missing?**
Open an issue in the **Issues** tab with the input you used. Issues are answered quickly.

***

### ⚖️ Legal

This actor collects only publicly visible product information (prices, titles, ratings). It does not collect personal data.
You are responsible for making sure your use complies with the target website's terms and with applicable law.

# Actor input Schema

## `searchTerms` (type: `array`):

Terms to search for on the selected eMAG site, e.g. "iphone 15".

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

Search, category or product URLs on emag.ro, emag.bg or emag.hu. Product URLs (containing /pd/) are scraped directly.

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

eMAG site used for search terms.

## `maxItems` (type: `integer`):

Maximum number of products to save.

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

Residential proxy is required: eMAG blocks datacenter IPs. The country is set to the site's country automatically.

## `scrapeDetails` (type: `boolean`):

Open each product page to get brand, seller, stock and category. Slower and uses more proxy traffic.

## `debug` (type: `boolean`):

Store page diagnostics (counts only) in the dataset.

## Actor input object example

```json
{
  "searchTerms": [
    "iphone 15"
  ],
  "startUrls": [],
  "country": "ro",
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "scrapeDetails": false,
  "debug": false
}
```

# Actor output Schema

## `products` (type: `string`):

No description

# 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 = {
    "searchTerms": [
        "iphone 15"
    ],
    "startUrls": [],
    "maxItems": 20,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("polyglot-data/emag-product-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 = {
    "searchTerms": ["iphone 15"],
    "startUrls": [],
    "maxItems": 20,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("polyglot-data/emag-product-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 '{
  "searchTerms": [
    "iphone 15"
  ],
  "startUrls": [],
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call polyglot-data/emag-product-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,polyglot-data/emag-product-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/fFGuG6DtexfhSXn9v/builds/dSMvlPVLO871LleRt/openapi.json
