Groupon Local Deals Scraper and New-Deal Alert (US) avatar

Groupon Local Deals Scraper and New-Deal Alert (US)

Pricing

from $1.40 / 1,000 deal scrapeds

Go to Apify Store
Groupon Local Deals Scraper and New-Deal Alert (US)

Groupon Local Deals Scraper and New-Deal Alert (US)

Groupon local deals for any US city and category, one flat row each: title, merchant, price, original value, discount %, rating and review count, location, distance, deal URL - and whether each deal is new or re-priced since the last run.

Pricing

from $1.40 / 1,000 deal scrapeds

Rating

0.0

(0)

Developer

Superslow Sloth

Superslow Sloth

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

5 days ago

Last modified

Share

Read the deals on Groupon's US city and category pages, one flat row each, and see which ones are new since your last run or have changed price. Give it cities (and optionally categories and sort orders), schedule it, and turn on Only new and re-priced deals to get an alert feed that costs nothing for deals you have already seen.

No account, no login, no Groupon API key. It reads the public local pages the same way a browser does.

Input

FieldNotes
citiesCity slugs as in groupon.com/local/<slug>: los-angeles (default), chicago, new-york, ... A full groupon.com/local/<slug> URL also works.
categoriesCategory slugs as in groupon.com/local/<city>/<slug>. Empty (default) reads only the plain city page. The eight top-level ones: things-to-do, food-and-drink, beauty-and-spas, automotive, retail, personal-services, home-improvement, health-and-fitness. Sub-categories such as restaurants also resolve.
sortsAny of relevance (default), rating, price:asc, price:desc, distance.
maxItemsStop after this many distinct deals (default 100).
changesOnlyReturn and charge only deals that are new or re-priced since the last run for the same cities.
proxyConfigurationRequired, Apify datacenter proxy by default. A run with no proxy stops before it fetches or charges anything.

How many deals a page gives, and why there are categories and sorts

Groupon's server renders only the first screen of deals for a page: 9 on a city or category page (25 on the New York State page, 66 on one automotive fetch). The rest are loaded by a call its own page makes in the browser, and the ?page=N parameter is ignored (pages 0, 2, 3, 50 and 500 of Los Angeles each returned an ordinary first screen of 9 and never a later one, measured 2026-10-07). What does change the first screen is the category page and the sort order: the Los Angeles city page plus its eight top-level categories, each in all five sorts (45 requests), returned 49 distinct deals. So the way to read more deals is a longer list of categories and sorts, not a bigger maxItems.

Two more things measured on the same day:

  • The same URL fetched twice can return a different first screen. Groupon A/B-tests two front ends (next and tanstack) and a different ranking comes with them. This actor reads the same fields from both.
  • Groupon has no newest-first sort, so a "new" deal can show up anywhere in a feed, and a deal that was on Groupon all along can look new if an earlier run happened not to see it. The memory fills up over the runs: a longer list of categories and sorts makes that happen less.

Unknown cities

Groupon does not return a 404 for a city or category it does not have: it answers 200 with the generic /local page (or the parent city). This actor compares the page's canonical link with the one it asked for, discards the tiles when they differ, and reports the page in the run log instead of labelling another place's deals with your city.

Output

FieldNotes
changenew, price_drop, price_rise or unchanged, compared with the previous run for the same cities.
deal_id, deal_uuid, urldeal_id is the /deals/<slug> slug and is what change tracking keys on. url is https://www.groupon.com/deals/<slug> without the tracking query.
title, merchant, merchant_location_countThe merchant is the line above the title (a chain's name for a chain); merchant_location_count is the "(443 Locations)" beside it.
price, currencyGroupon's price, in USD.
original_valueThe crossed-out value. Null when the tile shows none.
discount_percentThe percentage on the red badge as Groupon publishes it. With a sale price it is measured to the sale price (value 94, price 69, sale price 62.10 is "-34%"), so it is not always 1 - price / original_value.
sale_priceThe price after Groupon's sitewide sale, when the tile shows one.
promo_price, promo_code, promo_ends_atThe price with the promo code applied, the code, and when it ends (ISO-8601 UTC).
valid_throughWhen the deal stops being sold, from the page's schema.org data. Often absent.
rating, rating_countGroupon's star rating and its number of ratings. Null for a deal with none.
location, distance_text, distance_milesThe tile's location line (a neighbourhood or a street address) and its distance as printed, plus the number when it is in miles. The distance is measured from Groupon's reference point for the page - the city centre on every page read - not from you.
badge, is_sponsoredThe label on the tile's image ("Popular Gift", "10% Cashback"), and Groupon's own sponsored flag.
image_url, redemption_location_idThe tile image, and which location of a multi-location deal the tile links to.
city, categoryThe page the row was read from. A deal listed on several pages carries the first one this run read it on.

Honest nulls

A field Groupon did not give is null, never 0 or "". original_value is null for a deal shown without a value, discount_percent null for one without a badge - a 0 would read as a deal with no discount, which is a different claim. rating is null for a deal with no ratings, not 0 stars.

No "bought" count

The tile does not show how many people bought a deal, and neither the tile's data nor the page's schema.org list carries it, so there is no such column.

Where the fields come from

Each tile carries Groupon's tracking JSON in a data-bhd attribute: title, prices (in cents), discount, location line, rating, image. Merchant, distance and badge are read off the tile's text. The deal expiry comes from the page's schema.org ItemList, which can also list a deal that has no tile in the page as received - such a deal is still returned, with the tile-only fields null.

Change tracking

The memory (deal id to price) lives in a named key-value store on your Apify account, groupon-deals-watch, so no one else can see it. It is keyed on the set of cities, not on categories or sorts: those are only different views onto the same city's deals, so adding a category reports that category's unseen deals as new and leaves the ones already seen unchanged. The first run for a set of cities labels every deal new. From the second on, a deal is new if no earlier run saw it, price_drop / price_rise if price moved, and unchanged otherwise. With changesOnly, unchanged deals are neither returned nor charged.

Pricing

Pay per event: $0.002 per run (actor-start, charged after your input is validated, so a run that fails on bad input costs nothing), and $0.0014 per deal row written (deal-scraped). With changesOnly, unchanged deals are not charged.

Proxy and blocking

Groupon is behind Cloudflare. A plain request is answered with HTTP 403 and a "Just a moment..." challenge page; measured 2026-10-07 with a default client from an ordinary connection, and from Apify's own IP address on both days it was probed. Apify datacenter proxy exits were answered with the real page, so the proxy is mandatory here. A 403, a 429, a 5xx, and a 200 that turns out to be the challenge are all retried from a fresh exit address; a page that is not Groupon's at all is treated the same way. The actor presents a browser's TLS fingerprint (curl_cffi, current Chrome).

Each page is 0.8 to 1.3 MB of HTML, about 9 deals, so proxy traffic is roughly 100 KB per deal.