# eMAG Price Watcher (`smarcell/emag-price-watcher`) Actor

Snapshot public eMAG.hu / eMAG.ro product pages: title, price, currency, stock. HTML only, no login.

- **URL**: https://apify.com/smarcell/emag-price-watcher.md
- **Developed by:** [Seres Marcell](https://apify.com/smarcell) (community)
- **Categories:** E-commerce, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 product snapshots

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?

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 this Actor do?

**eMAG Price Watcher** stores a point-in-time snapshot of **public** [eMAG.hu](https://www.emag.hu/) product pages (and, optionally, [eMAG.ro](https://www.emag.ro/)): URL, title, displayed price, currency, and availability.

It sends plain HTTPS GET requests with [httpx](https://www.python-httpx.org/) and reads **public HTML** (schema.org JSON-LD `Product` / `Offer`, visible price and stock markup, and the inline `EM.offer` object when the page includes it). There is **no eMAG login**, **no marketplace seller API**, **no invented API keys**, and **no captcha or challenge bypass**. Amazon and LinkedIn URLs are rejected.

This is a **price snapshot**, not a purchase, quote, or stock reservation. eMAG prices, promotions, and availability change. What you get is whatever the public page showed at `scrapedAt`. It is **not a guarantee** of the price you will pay at checkout.

### Ready-to-run examples (no setup)

- [USB cable prices on eMAG.hu](https://apify.com/smarcell/emag-price-watcher/examples/emag-usb-cables-hungary)
- [Laptop prices on eMAG.hu](https://apify.com/smarcell/emag-price-watcher/examples/emag-laptop-prices-hu)

### Why use it?

- Keep a dated record of displayed prices for a list of product URLs you already have.
- Optionally collect product links from a public eMAG search listing and snapshot those pages too.
- Export JSON / CSV / Excel from the Apify dataset, or schedule runs on the platform if you want a recurring check.

This Actor does not add items to a cart, create accounts, watch private wishlists, scrape reviews in bulk, or monitor sites other than eMAG.hu / eMAG.ro.

### What data can it extract?

| Field | Type | Description |
| --- | --- | --- |
| `url` | string | Canonical public product URL |
| `productId` | string or null | eMAG product ID from the `/pd/...` URL |
| `title` | string or null | Product name from JSON-LD or the public page title |
| `price` | number or null | Current displayed offer price |
| `originalPrice` | number or null | Previous/strikethrough price when shown on the page |
| `currency` | string or null | ISO code (`HUF`, `RON`) |
| `availability` | string or null | Stock wording or schema.org token |
| `scrapedAt` | string | UTC time of the snapshot |

Missing fields stay `null`. Marketplace listings often show a **seller’s** offer on the product page; the Actor records that displayed offer, not a hidden or logged-in price.

### How to use

1. Open **Input**.
2. Paste one or more **Product URLs** (`https://www.emag.hu/.../pd/...` and/or `https://www.emag.ro/.../pd/...`).
3. Optionally set **Search query** and **Search marketplace** (`emag.hu` default, or `emag.ro`). **Maximum search items** defaults to 20.
4. Run. Rows land in the default dataset.

You must provide `productUrls` and/or `searchQuery`. Direct product URLs are all fetched (up to 100). `maxItems` only caps how many extra links are taken from search.

Locally, after installing the [Apify CLI](https://docs.apify.com/cli) and Python 3.12 dependencies:

```bash
cd emag-price-watcher
pip install -r requirements.txt
apify run --input-file example_input.json
```

Do not put API tokens in Actor input. eMAG public pages do not use an API key. Apify platform credentials are only for `apify push` / cloud runs and stay in your CLI or Console — this project does not ship keys, and it is not set up to push itself.

### Input

See the **Input** tab for the form. Fields:

| Field | Required | Default | Notes |
| --- | --- | --- | --- |
| `productUrls` | no\* | — | HTTPS eMAG.hu / eMAG.ro product URLs. Other hosts (including Amazon and LinkedIn) are rejected. |
| `searchQuery` | no\* | — | Public search string. Combined with `marketplace` into `/search/<query>/`. |
| `marketplace` | no | `emag.hu` | `emag.hu` or `emag.ro`. Used only for search. |
| `maxItems` | no | `20` | Integer 1–100. Caps search results only. |

\* At least one of `productUrls` or `searchQuery` is required.

Example (`example_input.json`):

```json
{
  "productUrls": [
    "https://www.emag.hu/pzx-v188-usb-c-usb-c-kabel-gyorstoltes-es-adatatvitel-pd-100w-1m-fekete-v188-type-c-c/pd/D4C7983BM/"
  ],
  "searchQuery": "",
  "marketplace": "emag.hu",
  "maxItems": 20
}
```

Search-only example:

```json
{
  "searchQuery": "usb kabel",
  "marketplace": "emag.hu",
  "maxItems": 20
}
```

### Output

Download the dataset as JSON, HTML, CSV, or Excel.

Example item (illustrative; live prices differ):

```json
{
  "url": "https://www.emag.hu/pzx-v188-usb-c-usb-c-kabel-gyorstoltes-es-adatatvitel-pd-100w-1m-fekete-v188-type-c-c/pd/D4C7983BM/",
  "title": "PZX V188 USB-C – USB-C kábel, gyorstöltés és adatátvitel, PD 100W, 1m, Fekete",
  "price": 1490,
  "currency": "HUF",
  "availability": "Nincs raktáron",
  "scrapedAt": "2026-08-28T15:20:00Z"
}
```

### Honest limits

- **Public pages only.** If eMAG returns a login wall, captcha, HTTP 403/429, or a bot challenge, the Actor logs it and stores an empty snapshot for that URL. It does not solve captchas, rotate residential proxies by default, or reuse cookies from a logged-in session.
- **HTML, not a private API.** Listing cards that are filled only after JavaScript may be missing from search HTML. In that case search returns fewer URLs than `maxItems`. Product detail pages used for this Actor still embed JSON-LD and price markup in the first HTML response when they are publicly available.
- **Prices change.** Promos, seller changes, VAT display, and “lowest price in 30 days” strikethroughs can differ from the number stored here. Checkout can add shipping, coupons, or Genius terms. Treat every row as a historical observation, not a contract.
- **Availability is what the page said.** “raktáron” does not reserve stock.
- **ToS and robots.** You are responsible for using this in line with eMAG terms and applicable law. This Actor is a convenience wrapper around pages anyone can open in a browser; it is not an official eMAG integration.
- **Scope.** `emag.hu` and `emag.ro` product/search pages only. Not Amazon, not LinkedIn, not other eMAG country sites unless you pass an allowed product URL (only `.hu` and `.ro` hosts are allowed).

### Pricing

- **Pay-per-event:** each stored product snapshot is billed as event `product-snapshot` when monetization is enabled.
- Suggested price point: **$0.002–0.005 per product** — competitive for price monitoring use cases.
- Apify FREE tier ($5/month credits) covers extensive testing.
- Direct `productUrls` are always scraped; `maxItems` only caps search discovery.

Platform compute is minimal (HTTP-only, no browser).

### Changelog

#### 0.2

- Pay-per-event billing (`product-snapshot`)
- `productId` and `originalPrice` fields
- Parser unit tests

#### 0.1

- Initial public HTML snapshots for eMAG.hu / eMAG.ro product pages and optional search.

### Related Actors

- [Hungary Procurement Monitor](https://apify.com/smarcell/hungary-procurement-monitor) — public sector tender monitoring
- [Website Contact Extractor](https://apify.com/smarcell/website-contact-extractor) — enrich seller domains with contact data

# Actor input Schema

## `productUrls` (type: `array`):

Public product pages to snapshot, e.g. https://www.emag.hu/.../pd/.... Also accepts https://www.emag.ro/... product URLs. Each listed URL is fetched (up to 100). Amazon, LinkedIn, and other hosts are rejected.

## `searchQuery` (type: `string`):

Optional public eMAG search term. The Actor opens /search/<query> on the selected marketplace and collects product links from the HTML listing (no login). Use this and/or productUrls.

## `marketplace` (type: `string`):

Host used when searchQuery is set. productUrls already include their own host, so Hungarian and Romanian product links can be mixed.

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

Maximum number of product URLs to collect from searchQuery. Direct productUrls are always scraped (up to 100) and are not reduced by this cap.

## Actor input object example

```json
{
  "productUrls": [
    "https://www.emag.hu/pzx-v188-usb-c-usb-c-kabel-gyorstoltes-es-adatatvitel-pd-100w-1m-fekete-v188-type-c-c/pd/D4C7983BM/"
  ],
  "searchQuery": "usb kabel",
  "marketplace": "emag.hu",
  "maxItems": 20
}
```

# Actor output Schema

## `snapshots` (type: `string`):

Public product snapshots stored in the default dataset.

# 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 = {
    "productUrls": [
        "https://www.emag.hu/pzx-v188-usb-c-usb-c-kabel-gyorstoltes-es-adatatvitel-pd-100w-1m-fekete-v188-type-c-c/pd/D4C7983BM/"
    ],
    "searchQuery": "usb kabel"
};

// Run the Actor and wait for it to finish
const run = await client.actor("smarcell/emag-price-watcher").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 = {
    "productUrls": ["https://www.emag.hu/pzx-v188-usb-c-usb-c-kabel-gyorstoltes-es-adatatvitel-pd-100w-1m-fekete-v188-type-c-c/pd/D4C7983BM/"],
    "searchQuery": "usb kabel",
}

# Run the Actor and wait for it to finish
run = client.actor("smarcell/emag-price-watcher").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 '{
  "productUrls": [
    "https://www.emag.hu/pzx-v188-usb-c-usb-c-kabel-gyorstoltes-es-adatatvitel-pd-100w-1m-fekete-v188-type-c-c/pd/D4C7983BM/"
  ],
  "searchQuery": "usb kabel"
}' |
apify call smarcell/emag-price-watcher --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,smarcell/emag-price-watcher"
        }
    }
}

```

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/O9yIEEFAgZYW4Rb0O/builds/3Z0MeHlydpmozKpfw/openapi.json
