eMAG Products & Price Scraper (RO / BG / HU)
Pricing
from $1.05 / 1,000 results
eMAG Products & Price Scraper (RO / BG / HU)
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
5 days ago
Last modified
Categories
Share
Scrape product listings from eMAG — the largest online marketplace in Romania, Bulgaria and Hungary.
What you get
One row per product (recordType: PRODUCT):
productId · offerId · pnk · productName · productUrl ·
priceValue · oldPriceValue · discountPercent · currency ·
ratingAverage · reviewCount · categoryName · categoryTrail ·
departmentId · availabilityCode · isGenius · hasUnfairPrice ·
listingPosition · pageNumber · searchRank
Plus a SEARCH_SUMMARY per listing and an ERROR row per failed input, so
every input maps to at least one row.
Two ways to point at a listing
{ "searchQueries": ["laptop", "casti bluetooth"], "country": "RO" }
{ "categoryUrls": ["https://www.emag.ro/laptopuri/c"], "country": "RO" }
Both produce identical PRODUCT rows. Use categoryUrls when you need
exactness — and read the next section for why that matters.
The two search traps — read these
1. A keyword search can redirect into a curated category.
/search/laptop 302s to /laptopuri/c. The rows then describe that
category, not your keyword, and the count differs. Not an error, but you
should know: every summary row carries redirectedToCategory and finalUrl.
2. A keyword eMAG cannot match still returns 60 confident products. There is no "no results" page. eMAG fuzzy-matches into some department:
| Query | eMAG's own headline |
|---|---|
zzqqxxnonsense12345 | 193 de rezultate in Piese auto pentru "zzqqxxnonsense12345" |
qwertyuiopasdfgh999 | 200 de rezultate in Piese auto pentru "qwertyuiopasdfgh999" |
Zero overlapping product IDs between those two — so it is not one fixed fallback set, it is genuinely different junk each time, with a confident count attached. Six "no results" phrasings were searched for in the HTML; none exists.
There is no gate that can be trusted, so this actor guesses nothing. It
emits eMAG's own headline verbatim as upstreamResultsText, with the
department parsed out as matchedDepartment, and logs it. If your electronics
query landed in car parts, you will see it. categoryUrls is the exact
alternative.
Rate limiting — the thing that will actually bite you
eMAG answers a client that has burst with HTTP 511 and a 3 KB body, and the block persists for minutes on that exit IP.
It looks like a TLS allowlist at first: an initial ladder had 8 of 9 profiles
on 511 with only safari18_0 at 200. Re-testing the same profile over time
disproved that —
t+0s chrome124 → 200 (1.22 MB)t+15s chrome124 → 200 (1.22 MB)t+60s chrome124 → 511t+135s chrome124 → 511
— the ladder had simply been run after a burst. So:
- the defaults here are deliberately slow: 2 concurrent, 1.5 s between request starts
- recovery rotates the exit IP, not just the fingerprint — the throttle keys on IP
- Residential proxy is the default, and what matters is pool size, not stealth: a datacenter range exhausts into the same block
- a run that still cannot get through emits a
rate_limitedERROR row saying exactly that, rather than an empty dataset
Known limits
- No detail-page pass. The listing card already carries name, both prices, rating, review count, the full category trail and all three ID systems — and the detail page sits behind the same per-IP throttle. A detail pass would multiply requests against the one resource this target meters, to re-fetch most of what you already have.
availabilityCodeis passed through raw (1/2/3). eMAG does not document the mapping publicly and it was not verifiable by observation, so no invented labels.- Seller name is not on the listing card. Only the Genius badge and the offer ID are.
Extraction
No JSON blob carries the listing. The single application/ld+json block on a
listing page is an FAQPage, not products, and div.card-v2 is an empty
shimmer placeholder — reading it returns 78 blank cards. The real data is in
data-* attributes on div.card-item.card-standard (60 per page,
server-rendered, complete).
Pagination is honest: pages 1/2/3/10 share zero product IDs, and past the
end pages shrink then empty rather than re-serving page 1 (p50 → 60 cards,
p100 → 18, p200 → 0, against a category reporting 5,958 products). The
whole catalogue is reachable.
Policy
emag.ro/robots.txt names no AI crawler, and /search/ and the /<category>/c
listing paths are allowed for User-agent: *. Only public product listings
are read — no login, no user data, no personal profiles.