Skip to main content

Google Maps collection

A Google Maps scraper that shows where every value came from.

Give it a list of keywords and a list of places. It searches Google Maps for every combination and returns one row per business, with the connector, the source and the time recorded against every field it stored.

Before anything else

Source
Google Maps listings
Affiliation with Google
None
Access
Operator-provisioned

NanoScraper is not affiliated with, endorsed by or sponsored by Google. Google Maps is named here as the source the connector reads.

Keywords, places, and the multiplication between them.

Two lists, one entry per line. Every keyword is run against every place, and each pairing is its own search.

Seven lines of typing, twelve searches

Keywords

  • dentist
  • dental practice
  • orthodontist

Places

  • Leeds
  • Manchester
  • Bristol
  • Sheffield

Searches

12

Language, scroll depth, map zoom and a results cap are set alongside the two lists. The cap applies per collection.

One search at a time, at roughly thirty-five seconds.

Throughput is the binding constraint here, so it is the number quoted first rather than the one left out.

  1. 0135 sOne search, roughly, start to finish.
  2. 0210The most searches a single job accepts.
  3. 0312 minHow long the connector waits for one job, by default.
  4. 044 days100 keywords × 100 places — 10,000 searches.

Which is why a plan is not a job

A campaign is a named plan — your keywords by your places — that expands into many jobs and works through them on its own. One job cannot hold ten thousand searches, and four days is longer than any single run should live.

The work list is a table rather than a variable, because four days spans a redeploy, a dead worker and somebody pausing it. A sweep every ninety seconds does at most one thing per campaign, so nothing races ahead.

One row per business.

Not one row per page read, and not one per time a business was seen. These are the columns the export actually carries, in order. Two of them arrive empty from this source, and the file says which rather than looking complete.

  1. 01Name
  2. 02Domain
  3. 03Website
  4. 04Phone
  5. 05Languagenever filled from this source
  6. 06Descriptionempty in every row measured
  7. 07Category
  8. 08Address
  9. 09Latitude
  10. 10Longitude
  11. 11Rating
  12. 12Review count
  13. 13Opening hours
  14. 14Listing URL
  15. 15Place ID
  16. 16CID

Found twice, stored once

Two searches that both return the same business produce one record, updated in place. Matching runs on the identifier the listing itself carries, so a business that renames itself or is spelled differently in two languages still matches.

A business with no website keeps an empty website. Borrowing the listing address instead once merged unrelated companies into one, because every listing shares a single host — and it asserted a site the source never claimed.

Two identifiers, and they are not interchangeable

CID

3669834603025597947

The number in a maps.google.com/?cid= link. Identity is derived from this.

Place ID

ChIJ…

The token the Google Places API accepts. Kept under its own name, unchanged.

Both are kept, each under its own name. Storing one under the name of the other produces a column the Places API rejects.

Google Maps carries no email addresses, so nothing here invents them.

A Maps listing does not carry one, so the stored payload has no email key. The engine can be told to open each website and hunt for an address; this connector pins that off. A tool that hands you an email from a Maps listing went looking elsewhere for it.

Two fields, and only one of them exists

absent is not empty

Email addressNot a column that exists. The collection screen shows it greyed out rather than offering a tick that returns nothing.
Phone numberPublished by most listings, and stored as the business's contact number when it is.

A contact collected this way carries a phone number and no email address, because the listing it came from had no email address to carry.

A missing value stays blank. Nothing is borrowed from another record and nothing is guessed, because an invented fragment in the evidence table is worse than an empty one.

Every value keeps the observation behind it.

Field by field, not record by record. Different fields on one business routinely come from different observations, and collapsing that would assert one source produced the whole row.

Four exports on companies

  • CSV

    The records the current filters select, one row each.

  • Excel

    The same rows and the same columns, as a workbook.

  • Evidence CSV

    One row per stored piece of evidence, not one per business.

  • Excel + evidence

    Two sheets, Records and Evidence, joined on Record ID.

What the evidence file carries

  1. 01Record ID
  2. 02Company
  3. 03Field
  4. 04Stored value
  5. 05As observed
  6. 06Connector
  7. 07Connector version
  8. 08Source
  9. 09Observed at

As observed is what the source said before it was normalised. It is legitimately blank when nothing distinct was stored — a phone number the listing already printed in the stored form has no second version.

How the raw observation and the canonical record stay separate is set out in where every value came from, and the collection path itself in how collection works.

Three things this cannot tell you.

Each is a property of what the source publishes, written down here rather than discovered after the first export.

01Which search found a business
The engine tags each batch of rows with a random identifier and publishes no mapping back to the keyword. “This one came from Lyon” is not something this pipeline can say, so counts belong to the batch rather than the search.
02Whether a listing is true
What is recorded is what the listing published and when it was read. Whether a phone number still reaches the business is not knowable from inside NanoScraper, and nothing here estimates it.
03Everything a search could return
Scroll depth bounds how far each result list is read, and the results cap applies per collection, not per search. A run returns what it reached inside those two numbers, and both are yours to set.

The other sources, briefly

Google Maps is one connector of four. The others read a page you name, parse markup, or reach a separately run service over HTTP. All of them sit behind the same boundary and produce observations in the same shape.

The collection here is real and it is small: a few hundred businesses. Nothing on this page describes a volume that has been run.

Ask for an account and start collecting.

Access is provisioned by the operator; there is no self-service registration. Tell us what you want to collect and where. A person reads it — there is no automatic reply, and no response time is promised here that does not exist.

Request access

NanoScraper is not affiliated with, endorsed by or sponsored by Google. Google and Google Maps are trademarks of their respective owner, named here only as the source this connector reads.