eMAG Products & Price Scraper
Pricing
from $1.05 / 1,000 results
eMAG Products & Price Scraper
Scrape product listings from eMAG, the largest online marketplace in Romania, Bulgaria and Hungary. Every row carries both prices, the discount, rating, review count, the full category trail, Genius status and all three product IDs. Search by keyword or walk an exact category URL.
Pricing
from $1.05 / 1,000 results
Rating
0.0
(0)
Developer
Ibnu Adzim
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
16 hours ago
Last modified
Categories
Share
eMAG Products Scraper (RO, BG, HU)
Product listings from eMAG — the largest online retailer in Romania, and also serving Bulgaria and Hungary — as structured rows: price in the local currency, rating and review count, the full category branch, badges, and eMAG's own stable product codes.
The thing that makes this different
eMAG answers a search it cannot satisfy with 60 unrelated products, not with zero.
Ask for qwertyuiopasdfgh and you get HTTP 200 and a full page of lipsticks
and vacuum nozzles. Ask for iphone filtered to a brand that has no iPhones
and you get a Sudoku book and a vitamin supplement. In every failing case the
result set overlaps the correct one by exactly zero products — eMAG
silently drops the keyword and serves a generic catalogue page.
The rows are real products with real prices. They are simply not an answer to the question you asked, and nothing in the response says so: there is no echo field naming the query eMAG actually ran.
So this Actor checks the output. Every search reports keywordMatchShare —
the fraction of returned titles that actually contain your keyword — and a
search where nothing matches is returned as a keyword_dropped error row
rather than 60 products you would have to notice were wrong. Verified in a
cloud run: qwertyuiopasdfgh produced an error and zero products while
telefon samsung, in the same run, produced 60 rows at a share of 1.0.
And the prices are a trap in their own right. eMAG renders 6,999.99 lei as
6.999 plus a superscript 99, Romanian-style — . for thousands, , for
decimals. float("6.999") gives you 6.999: wrong by a factor of a thousand,
and still a plausible-looking price that nothing downstream will flag. Every
row carries both the parsed number and priceRaw ('6.999,99 Lei') so the
arithmetic is auditable.
What you get
One SEARCH_SUMMARY row per keyword or category, then one PRODUCT row each.
| Group | Fields |
|---|---|
| Identity | productId, offerId, partNumberKey, name, url |
| Price | price, priceRaw, priceCurrency, previousPrice, previousPriceRaw |
| Reviews | ratingValue, reviewCount |
| Category | categoryId, categoryName, categoryTrail (full branch), departmentId |
| Commerce | badges, isGenius, availabilityId, hasUnfairPrice |
| Media | imageUrl |
| Provenance | _input, _source, _scrapedAt, country, sourceHost, resultPosition, pageFound |
partNumberKey is eMAG's own PNK — the code in the /pd/<PNK>/ URL — which
stays stable when a seller edits the title.
categoryTrail is the full branch, e.g.
["Laptop, Tablete & Telefoane", "Telefoane mobile & accesorii", "Telefoane Mobile"].
Honesty counters on every summary
| Field | What it tells you |
|---|---|
keywordMatchShare / keywordHeld | whether eMAG actually ran your search |
ratedRows / ratedShare | eMAG renders ratings server-side only some of the time; this says how many you got rather than letting a quiet run look like "these products have no reviews" |
pricedRows / rowsWithoutPrice | how many rows carry a usable price |
challengesRetried | eMAG's rate-based challenge, absorbed by retries — if this is high, raise minRequestInterval |
stoppedReason | no_new_ids, max_pages or max_items, so a short run is never ambiguous |
duplicateRowsDropped | ids that repeated across pages |
Input
| Field | Notes |
|---|---|
country | ro, bg or hu. Sets the host, the currency and the Accept-Language. |
keywords | Keywords to search, one run each. Each is keyword-checked (see above). |
categoryPaths | Browse whole categories instead — eMAG's own path segment, e.g. telefoane-mobile. Not keyword-checked, because there is no keyword to hold. |
maxPages | Pages of ~60 products. |
maxItems | Overall cap on product rows; summaries do not count against it. |
minRequestInterval | Raise this first if a run reports retried challenges. |
Only these three countries are offered: they are the eMAG sites whose own
robots.txt permits this, each checked separately. Any other country is
refused at input validation with the reason.
Limits, stated plainly
- Pagination is path-based. eMAG accepts
?p=2and silently returns page 1; this Actor uses/p2, which genuinely advances. If you build your own URLs, do the same. - eMAG runs a rate-based bot challenge, including one variant that arrives
as HTTP 200 with a captcha title and zero cards. Both shapes are detected and
retried. Keep
maxConcurrencylow. - Ratings are not always rendered. The share is reported per run.
Method, measurements and the full trap list: CRAWLING_METHOD.md.