Google Maps Business Posts Scraper: GBP Updates, Offers, Events avatar

Google Maps Business Posts Scraper: GBP Updates, Offers, Events

Pricing

$1.00 / 1,000 post delivereds

Go to Apify Store
Google Maps Business Posts Scraper: GBP Updates, Offers, Events

Google Maps Business Posts Scraper: GBP Updates, Offers, Events

Scrape the posts a business publishes on its Google Business Profile (GBP, GMB): updates, offers with coupon codes and terms, events with dates, photos, videos and buttons. By Maps link, place id, CID, name, or a search like "dentist in Austin". No login. Export to JSON, CSV or Excel, or via API.

Pricing

$1.00 / 1,000 post delivereds

Rating

0.0

(0)

Developer

Steady Scrape

Steady Scrape

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

3 days ago

Last modified

Security

Limited permissions

Share

Google Maps Business Posts Scraper (Google Business Profile posts, GMB posts)

Scrape the posts a business publishes on its Google Business Profile, the "Updates" Google Maps shows on the business's page: what's new updates, offers with their coupon code, terms and redeem link, events with their start and end, photos, videos, hashtags, links and the post's button ("Call now", "Book", "Order online", "Learn more"). Newest first, as far back as Google keeps them (years).

Give the businesses by Google Maps link, place id, CID or "name, city", or give a search term such as dentist with a location, and the posts of the businesses Google Maps lists first are read. No login, no browser, no Google API key. Export the posts to JSON, CSV or Excel, or read them through the API.

What you can do with Google Business posts

  • Competitor monitoring for local SEO: see what the competitors around a client post, how often, which offers they run and which buttons they use. The ACTIVITY record ranks every business read by how recently and how often it posts.
  • Find businesses that stopped posting (an agency's sales list): a search for roofer in Denver with daysSinceLatestPost tells who has not posted in months, and a no_posts row who never did.
  • Collect local offers and events: postTypes: ["offer"] returns only offers, with the coupon code, terms and dates; ["event"] only events.
  • Archive a client's own posts: every post with its text, images and public post link, for reports or a migration.
  • Content research: what dentists, gyms or restaurants actually post, with the hashtags and links they use.

Input

fieldwhat it does
businessesOne per line: a Google Maps link (also maps.app.goo.gl share links), a place id (ChIJ…), a CID, or "name, city". Up to 500.
searchTermsSearches typed as in Google Maps (dentist, coffee shop in Portland). Up to 50.
locationWritten after each search term: dentist + Austin, TX is searched as dentist in Austin, TX.
maxBusinessesPerSearchHow many of the businesses Google Maps lists first per search are read (1–20, default 10).
maxPostsPerBusinessThe newest posts delivered per business (1–1,000, default 10).
postedWithinDaysOnly posts published in the last N days; 0 for any date.
postTypesOnly these kinds: update, event, offer, alert. Empty for every kind.
language, countryLanguage of labels such as "5 hours ago", and the country Google answers for (default en, us).

Input example

{
"businesses": [
"https://www.google.com/maps/place/Swish+Dental+Downtown/data=!4m2!3m1!1s0x8644b5b434046875:0x644e6eb422388b7a",
"15910258412779129905",
"Franklin Barbecue, Austin TX"
],
"searchTerms": ["dentist"],
"location": "Austin, TX",
"maxBusinessesPerSearch": 3,
"maxPostsPerBusiness": 20,
"postedWithinDays": 90
}

Output: one row per Google Business post

{
"rowType": "post",
"businessName": "Seven Grand",
"primaryCategory": "Bar",
"address": "405 E 7th St, Austin, TX 78701",
"website": "http://sevengrandaustin.com/",
"rating": 4.7,
"reviewCount": 729,
"cid": "15910258412779129905",
"placeId": "ChIJvYIs_6a1RIYRMcxe8rqXzNw",
"mapsUrl": "https://www.google.com/maps?cid=15910258412779129905",
"positionInBusiness": 1,
"postId": "2569776269900488028",
"postType": "offer",
"title": "Join Friends of the Bar: 350 Points + $10 Off",
"text": "Friends of the Bar is our free loyalty program. Sign up and we'll drop 350 bonus points on your account…",
"publishedAt": "2026-08-10T20:24:16.000Z",
"postedLabel": "Aug 10, 2026",
"startsAt": "2026-08-10T05:00:00.000Z",
"endsAt": "2026-11-09T05:59:59.000Z",
"scheduleLabel": "Valid Aug 10 - Nov 8",
"offerCouponCode": null,
"offerRedeemUrl": "https://www.toasttab.com/seven-grand-austin/rewardsSignup?utm_source=google&utm_medium=offer_post&utm_campaign=fotb_signup_2026q2",
"offerTerms": "New members only. 350 bonus points (about $5 in reward value) awarded after loyalty signup…",
"buttonType": "view_offer",
"buttonLabel": "View Offer",
"imageUrls": ["https://lh3.googleusercontent.com/geougc/AF1QipMz5vR5I3S9-Mpa3UWnwHmpczTVAnZ62K6NDlRz=h400-no"],
"videos": [],
"postUrl": "https://search.google.com/local/posts?q=Seven+Grand&ludocid=15910258412779129905&lpsid=CIHM0ogKEN6S--bj_q6hkgE&source=sh/x/loc/post&lsig=AB86z5UX894jlxgZsmwcQr-BT-is",
"source": "business",
"input": "15910258412779129905",
"searchQuery": null,
"searchRank": null
}

A business that delivered no post gets one free row saying why:

{
"rowType": "business",
"status": "no_posts",
"reason": "the business has published no posts on Google Maps",
"businessName": "Jays Home Auto Repair",
"cid": "13537352006029681092",
"latestPostAt": null
}

Post fields

fieldmeaning
rowTypepost for a post; business or search for a free row (see below)
postIdGoogle's id of the post
postTypeupdate (what's new), event, offer, alert (the COVID-19 notices of 2020–2021); null for a kind Google adds later
titleThe title of an event or an offer (updates have none)
textThe post's text, with its line breaks
links, hashtagsLinks written in the text, and hashtags without the #
publishedAt, postedLabelWhen it was published (ISO, UTC) and how Google shows it ("5 hours ago", "Aug 10, 2026")
expiresAtUntil when Google shows it: an event's or offer's end, or six months after an update
startsAt, endsAt, scheduleLabelAn event's or offer's dates, and as Google writes them ("Valid Aug 10 - Nov 8")
offerCouponCode, offerRedeemUrl, offerTermsAn offer's code, redeem link and terms and conditions
buttonType, buttonLabel, buttonUrl, buttonPhoneThe post's button: book, order_online, buy, learn_more, sign_up, view_offer or call, with its link or phone number
imageUrls, videosPhotos (400 px high; change =h400 in the link for another size) and videos (thumbnail and video link)
postUrlThe post's own public page
businessName, primaryCategory, address, phone, website, rating, reviewCount, cid, placeId, mapsUrlThe business
source, input, inputIndex, searchQuery, searchRank, positionInBusinessWhere the business came from (the input as typed and its position in its list), and the post's place among its posts
scrapedAtWhen the run read it (ISO, UTC)

Free rows

statuswhen
no_postsThe business has never posted (or deleted every post)
no_matching_postsIt has posts, but none of the kinds or dates asked; latestPostAt says when it last posted
business_not_foundThe link, id or name leads to no Google Maps place; a name that matches several places is not guessed
invalidNot a Google Maps link, id or name (a Yelp link, a Maps search link)
blockedGoogle refused every IP the run could ask from before the business's posts were read
spending_limitThe run's spending limit was reached before this business
no_results (search row)A search term Google Maps lists no business for

The ACTIVITY record

The run's key-value store also holds ACTIVITY: one entry per business read, most active first, with latestPostAt, daysSinceLatestPost, postsLast30Days, postsLast90Days, postsRead and allPostsRead. The counts come from every post read, at least the newest 100 per business even when you ask fewer, so a run of 10 posts per business still tells who posts weekly. SUMMARY holds the run's counts.

Pricing

US$0.001 per post delivered (US$1 per 1,000 posts). Free rows (no posts, not found, blocked, spending limit) are never charged, and the run stops at your spending limit. A business found by a search costs only its posts: the search itself is free.

How it reads Google Maps, and when Google asks for verification

It asks Google Maps the same questions its own web page asks when you open a business's "Updates" tab, at a person's pace, over HTTP: 100 posts per request, so a business with 139 posts takes two. If Google asks an IP for verification — its "unusual traffic" page, a CAPTCHA, a JavaScript check, or any answer that is not Google Maps' normal data — that IP is done for the run: nothing more is sent from it, and the run goes on from another IP of Apify's datacenter proxy. It never solves, bypasses or replays a challenge. Plain overloads (HTTP 429 or 5xx without a challenge) take the same way. When every IP the run can use has been refused, the posts already read are delivered, the businesses left get a free blocked row that says so, and the run ends successfully with a message to try again later.

Limits

  • Up to 500 businesses and 50 search terms per run; up to 20 businesses per search (Google Maps' first page of results).
  • Up to 1,000 posts per business, newest first.
  • A name is accepted only when the place Google finds carries that name; give the Maps link when a name is ambiguous.
  • Posts the business deleted cannot be read; expired offers and past events are still listed and are delivered.
  • Photos come as Google's image links; the Actor does not download files.

It reads posts businesses publish for anyone to see on Google Maps, without logging in, at a pace a person browsing the map could produce. Posts are business content, not personal data. Use the data in line with Google's terms and the laws that apply to you.

This Actor is not affiliated with, endorsed by or sponsored by Google. Google, Google Maps and Google Business Profile are trademarks of Google LLC.