# Changelog of Google Maps Scraper (`vortex_data/google-maps`) Actor

- **URL**: https://apify.com/vortex\_data/google-maps/changelog.md
- **Full Actor documentation**: https://apify.com/vortex\_data/google-maps.md

## Changelog

All notable changes to this Actor are documented here. Version numbers are
Apify build revisions.

### \[4.7.12] - 2026-09-16

#### Fixed

- Hotfix: pasted Place IDs and Maps URLs now get the add-ons the run asked
  for. A run whose input was `placeIds` or `startUrls` with
  `extractPlaceDetails` or `maxPhotosPerPlace` switched on came back with
  plain search rows — no full-week opening hours, star breakdown, review
  keywords, popular times or photo gallery. Searches were unaffected, and
  nothing was ever charged for the work that did not happen.

### \[4.7] - 2026-09-07

#### Added

- **Full place details** (`extractPlaceDetails`). Opens each saved place's own
  Maps page for the fields a search result never carries: opening hours for
  the whole week, the 1-5 star breakdown behind the average rating, the words
  reviewers keep repeating, how busy the place is by hour and day, how long
  people stay, the editorial summary, and what only some kinds of place have
  — fuel prices, EV connectors, people also search. One extra request per
  saved place, charged once per place actually enriched.
- **Photo gallery** (`maxPhotosPerPlace`). A search result carries one photo
  whatever the place is; this returns what the place's own record holds —
  measured at 3 photos for a village store and 240 for a national museum.
  Adds `photoGallery`, `photoGalleryUrls` and `photoGalleryCount`, and a
  *Photo gallery* view on the Output tab. It rides the same request as the
  details add-on, so switching both on costs one request per place rather than
  two. Charged once per place whose gallery came back, never per photo.

### \[4.6] - 2026-08-31

#### Fixed

- Where two maps read a Location differently, the run searches where the map
  that reads addresses puts it. `Tân Bình` was searched in Yunnan, 1,554 km
  from the district in Ho Chi Minh City; `Moscow region` in a village near
  Aktobe. The residential exit follows the place too, so a Vietnamese district
  is no longer searched through a Chinese one.
- A Location the map holds only as a labelled point no longer claims a
  boundary it does not have. A box the map computes from a place's rank —
  the same 4.4 km for towns all over the world — was being used to decide
  which results were inside the area asked for.
- Wards and communes written with their own country's word for them resolve to
  their real outline. `Xã Tân Tiến, tỉnh Đồng Nai` and its neighbours ended
  runs at zero; they now come back with the boundary the map holds.
- Where no map draws the area at all — an industrial estate, a ward — each
  result is marked in or out of it by how Google itself files the address.
  Rows from `Vapi GIDC` and `Tarapur MIDC` searches carried no area verdict at
  all before, so a list could not be filtered by the area it was asked for.
- A Location the map answers with somewhere else is told apart from one the
  map has never heard of, and gets the opposite advice. A correctly spelled
  district was being sent back to check its spelling.

### \[4.5] - 2026-08-27

#### Fixed

- A Location written the way its own country writes an address is understood.
  A place named together with the local word for *ward*, *regency*, *district*
  or *city* now finds that place, rather than whatever building happened to
  match the words, or nothing at all.
- The parts of a Location are separated by the punctuation its own language
  writes them with. An address typed with an Arabic or an ideographic comma is
  read as the several places it names rather than as one long name.
- A Location the map can only put on a single point is refused unless the map
  calls that point by the name that was asked for. A district the map no
  longer holds could be answered with a road on another continent and searched
  at street level from that country's address; it now ends with the warning
  that the Location could not be resolved.
- A Location that could only be put on a point is said in the run's `OUTPUT`
  record and in **Action needed**, not only in the log. A point has no
  boundary, so nothing the run returns can be checked against the area asked
  for.
- **By location** counts the places *inside* each requested area, rather than
  the places the search for that area happened to deliver first. Google reads
  a wide viewport loosely, so one area's search often returns places belonging
  to another.
- Three notes ran past the edge of their block when a Location or a search
  term was long, and the end of the line was lost.

### \[4.4] - 2026-08-27

#### Changed

- An area is also searched for the narrower trades it holds, not only split
  into quarters. A run reaches businesses that splitting alone does not, and
  the rows still come back under the term that was typed.
- Map areas are searched farthest-apart first. A run that stops on a place
  limit, a charge ceiling or the Timeout returns more places in the same time.
- An area whose results have run out is no longer searched again, so a run
  spends its time where places are still being found.

#### Fixed

- A long run keeps its resume point current, so a migrated or resurrected run
  does not repeat places it has already delivered.
- A run that ends in an error records where it stopped in its `OUTPUT` record.

### \[4.3] - 2026-08-25

#### Changed

- The run log is laid out as groups. A blank line separates one kind of line
  from another, so the progress pulse, the notes about a search area and the
  fields of a summary are told apart at a glance instead of running together
  as one block of text.
- Every note in **Search** names its subject in one column, so the run reads
  down a single edge whatever the note is about.
- The progress line is a fixed grid. Its columns are decided before the first
  one is printed and do not move, so two lines minutes apart can be compared
  straight down the page.
- A coloured mark means something again. 🟡 is something to decide and 🔴 is
  something that did not work; the routine lines that carried a blue or green
  circle now carry none.
- **Nothing is cut.** A search term, a Location or a place name that will not
  fit its column is printed whole and the words around it give way instead.
  Where a geocoder returns a name too long for a line — a ward, a municipal
  zone, a postcode and a country — the row keeps the part that says which
  place it is.
- **Action needed** asks for one change once. Three warnings that each ended
  in "name the Location more fully" produced three items; they produce one,
  and it is the one that tells you the most.
- The run plan no longer claims a time it cannot know. `Time ahead` says
  `if the caps fill`, because every figure in it assumes every search fills
  `maxCrawledPlacesPerSearch` and a search stops when the ground runs out.
- The warning that told you to search fewer terms or raise the Timeout is
  gone. It was built on that same figure, and measured against real runs the
  figure is two to ten times high.
- The results map is reported in **Result**, beside what the run charged for,
  rather than at the foot of the search.

#### Fixed

- A note that ended in a colon with nothing after it.
- Lines running past the edge of their own block: an ambiguous Location's
  resolved name, the list of what the run worked around, and the towns
  out-of-area results came from.
- A thousand written two ways in one log.
- A per-search cap far above what a map area can hold no longer makes the plan
  ask for more searches than the subdivision limit allows.

### \[4.2] - 2026-08-25

#### Changed

- **Action needed** lists only what the run could not do. What a setting cost
  you is stated as a fact under **Worth knowing**, without asking you to change
  a setting you chose.
- The **Action needed** block appears only when there is something to fix.
- Fields this Actor does not take are ignored. A run carrying `radius`,
  `maxItems` or anything else from another product returns exactly what the
  same run returns without them.
- A pasted coordinate's advice says which number in the snippet is yours to
  replace.
- Every Location you give gets one row in **Setup**, whatever became of it. The
  ones that did not resolve, and the one a strict run skipped, used to be loose
  sentences printed between the rows of the ones that worked, so the table was
  cut in half by the answer.
- **Action needed** no longer contains an item that begins "Nothing to fix". A
  term Google answers briefly is reported as a fact, because there is nothing
  to do about it.
- Advice that guessed is gone. A run whose answer held nothing new was told to
  "broaden the search term, or search a wider Location"; one that hit a network
  failure was told to narrow it "if it repeats"; one whose answer was short was
  told to search a wider Location "for a verdict". The run knows none of those
  helps, so it states what happened and leaves the choice to you.

#### Fixed

- A Location that already names its country is no longer told to name it fully.
  Only Locations left bare are called out, and they are named.
- A run that delivers from a country other than the one it searched now says
  so.
- Places hundreds of kilometres away are no longer described as "just outside
  the area"; they are counted and named separately from real neighbours.
- A run whose only results were far away names the towns they came from.
- The explanation of places with no verifiable location now reaches the runs it
  was written for.
- The same notice is no longer repeated for one search term.
- One drop is no longer reported twice, once with the towns named and once
  without.
- Every log line fits inside its block, blocks are separated by a blank line,
  and a thousand is written the same way throughout.
- Long notes are shown by their first sentence rather than running past the end
  of the line.
- Each Location's boundary result is reported on its own row in **Setup**.

### \[4.1] - 2026-08-24

#### Changed

- `emails` is ranked: the address a place publishes as its way in comes first.
  Nothing is dropped — a row that finds thirty addresses carries thirty.
- Form placeholders such as `your@email.com` are no longer saved as contacts.
  Of every address collected in one day, 27 of 3,588 were removed and none was
  a real business.

#### Fixed

- A run whose Timeout is two minutes or less now searches. It used to reserve
  the whole budget for its own wind-down and return nothing in five seconds.
  Runs of six minutes or more are unchanged.
- A Location that resolves into the wrong country is reported.
- A valid GeoJSON `Feature` is no longer called invalid after being accepted
  and searched.
- A run stopped by `maxTotalChargeUsd` is no longer told to raise its Timeout,
  and the places whose websites went unchecked name the limit that stopped the
  run.
- `Stopped by the run's time limit` prints the Timeout rather than how long the
  run lasted.
- A run that never reached Google is no longer told to check its spelling.
- A small area is no longer called too broad. Google answers around a place, so
  most of the answer always falls outside a neighbourhood; a wide area that
  behaves the same way still gets the warning.
- A run with no filters is no longer told its filters removed its results.
- One row of five hundred outside the area no longer raises an action.
- The **Result** block adds up. Two removals happened before a row could be
  counted as new, and printing them among the drops left the totals short.
- `Searching … → N` is the number of searches the run starts.
- The resolved area's width is the same number in the log and in `OUTPUT`.
- `OUTPUT` carries the proxy country, which was always empty, and the website
  pool that ran.
- A term is named once, not once per language.
- A run that drops places outside its area names the towns whatever ended it.
- A run given only `startUrls` gets a **Setup** block with its places limit,
  filters, time limit and add-ons.
- A whole trade list pasted into one search box is called out.

### \[4.0] - 2026-08-24

Three weeks of work in one release. Result prices are unchanged.

#### Changed

- The same thousand places take 33 seconds where they took 58, so a run that
  ends on its Timeout gets further through the list.
- The default machine is 4 GB, up to 8 GB: 1.9× quicker. Billing is per result,
  so this does not change what a run costs.
- Parsing a business website is twice as quick, and raising **Contact
  concurrency** costs far less time per site.
- Websites give up more contacts: pages are read to the end instead of to a
  fixed length. Over 348 real sites, contacts rose from 60.9% to 64.1%.
- A site that refuses the first request is asked once more as a different
  browser. Of 17 that refused, 4 opened.
- The run log is rewritten. **Setup** is every setting you are running under,
  **Run plan** is what the run will spend and expect, **Result** says how that
  went — one name per thing, every number once.
- A run that cannot fit its Timeout is told before it starts spending.
- Warnings and the status line are written to fit rather than trimmed
  mid-sentence.

#### Fixed

- `maxCrawledPlacesPerSearch` is honoured for `startUrls`. A pasted URL and the
  areas under it were counted against two separate caps.
- Every `startUrls` row carries `inputStartUrl` and `inputUserData`; before,
  only rows from that URL's first search did.
- A pasted coordinate's `customGeolocation` snippet is no longer cut off.
- A direct target Google refuses is reported as a refusal, not as a typo.
- Locations spanning several countries search from one steady exit.
- A site's contact page is no longer fetched twice under two spellings, so the
  freed attempt goes to a page not yet read.

### \[3.0.38] - 2026-08-08

#### Changed

- Direct targets are a phase of their own in the log, with progress every
  twenty seconds.
- A pasted Place ID is resolved through three routes: the place page, the
  `place/?q=` form, and the `?cid=` page the ID encodes.
- An ID that still fails is explained as stale. Google retires a Place ID when
  a listing is edited, moved or merged — re-copy the ID, or paste the place's
  URL.
- The relevance filter's description says what it is: best when a term names a
  kind of place, not a guarantee, and every row carries `searchTermMatch`
  either way.
- The log names things by what you would recognise — a failed target by its
  Place ID, an exhausted area by its search term, a long diagnosis by its first
  whole sentence.

#### Fixed

- A run whose residential proxy cannot be opened no longer fetches pasted Maps
  URLs or Place IDs from the worker's own address.
- The strict-mode area summary keeps every count on one line.

### \[3.0.37] - 2026-08-07

#### Fixed

- A run stopped by its charge limit before it could save a batch says the batch
  was not saved, with the count. It used to claim those places were saved
  without contacts or reviews. Nothing about what is saved or charged changes.

### \[3.0.36] - 2026-08-07

#### Changed

- One verdict column instead of two. `searchTermMatch` says which of four
  things the run concluded — `match`, `arguable`, `not-a-match` or
  `not-judged`. A saved filter on `matchesSearchTerm=true` becomes
  `searchTermMatch` is `match` or `arguable`; `=false` becomes `not-a-match`.
- The relevance judge runs only when `skipPlacesNotMatchingSearch` is on. A run
  that did not ask for filtering no longer loads the language model or reports
  judge statistics.
- Rows removed after an answer ran out of what you searched for are counted
  apart, as `paddingTailPlacesDropped`. The same rows are removed, under a more
  precise reason.
- With the filter on, a "no" that arrived before all of a place's search terms
  had answered now waits for the full evidence instead of being saved flagged.
  A run's Locations are searched one place at a time so verdicts settle within
  one wave.
- The judge's notes are said once per search term, not once per term in every
  Location.
- The **Search** block reads as a table: one opening line, notes aligned on one
  term column, counters right-aligned.
- One log message is one line. What does not fit gives way at whole units — a
  list shows whole items and counts the rest as `+2 more`, and a failed search
  names its reason as a phrase rather than a truncated traceback.
- The judge's notes use the dataset's own words: a term the run cannot judge
  reads "nothing to judge its rows by; saved as not-judged".
- Duplicate Place IDs in the input are folded and reported, as duplicate search
  terms already were.
- The word model costs far less CPU. No verdict moves.

#### Fixed

- A custom search area is searched at the size it was drawn. A polygon or a
  point with `radiusKm` was framed about four times too wide, so the run
  downloaded and discarded ground nobody asked about.
- A run given only Maps URLs or only Place IDs no longer fails before its first
  request.
- A run stopped while resolving Locations stops there and writes its summary,
  instead of geocoding on until the platform kills it.
- A run that reports itself as failed is reported as failed by the platform
  too.
- A run cut short by its charge limit counts what its last answer dropped, so
  the totals add up.
- `keepUnverifiedLocations` sent as the text `"false"` no longer switches it
  on.
- An unknown `reviewsSort`, and a `minRequestIntervalMs` that is not a number,
  are reported instead of changed in silence.
- The run summary names your search terms as you typed them.
- The summary counts how many Maps search URLs were given against how many were
  used.
- A run that cannot open the residential proxy is told to check the allowance,
  not to remove a `proxyConfiguration` it was never given.
- With website contacts on, a run whose budget covered only part of what it
  found could save none of it. What the budget covered is now enriched and
  saved before the run stops.
- The single row a run writes to explain saving nothing is no longer billed as
  a result.

#### Removed

- The `locatedIn` column, which was documented and always empty.
- The `matchesSearchTerm` boolean, replaced by `searchTermMatch` above.

### \[3.0.35] - 2026-08-06

#### Fixed

- A Location written as `district, state, country` keeps its own boundary
  instead of falling back to the centre of the state, so places found in it are
  no longer marked as outside the area.
- A Location with no boundary can no longer end the run, and one that resolves
  to a point says so in the log.
- A run that stops on an unexpected error writes the row explaining it and
  reports itself as failed instead of finishing quietly.

### \[3.0.34] - 2026-08-06

Everything below had been waiting behind the 2.0 line.

#### Changed

- Areas are searched deeper, and one thin area no longer retires a search term
  for the whole city.
- The Reviews view shows the review count and a link; the Overview shows the
  count beside the rating and one search-term column instead of two.
- With `skipPlacesNotMatchingSearch` on: about a quarter fewer places that are
  not what you searched for. A narrow search no longer returns the whole
  family, a two-word search no longer treats every shop in town as the trade,
  and a deep search stops saving the padding at the end of an answer.
- With the filter on, a place is no longer simply a match or not — the dataset
  says how firmly, and the summary counts the arguable rows beside the flagged
  ones.
- Search terms are understood in your own language: `panetteria`,
  `boulangerie`, `пекарня` and `パン屋` reach the same trade, from 18,606 words
  in 33 languages.
- The Actor knows the words Google itself uses for a trade, so a bakery is
  recognised as `Fornaio` in Italy.
- A search term with a place name in it names the trade inside it.
- A term that names a whole class of business is left alone.

#### Fixed

- Review counts are back on every place, with price ranges. The Actor was
  asking Google for a search's results before Google had filled them in, so
  `reviewsCount`, `reviewsUrl` and `price` were missing from most rows.
- The reviews link opens the reviews; it used to land on a search page.
- Wards and districts find their boundary where the city is also a province.
  They were searched by name, with no area to check results against.
- A run with `skipPlacesNotMatchingSearch` off no longer logs verdicts it did
  not act on.

### \[3.0.30] - 2026-08-02

#### Changed

- More of Google's area cards are recognised and dropped: a town, a district or
  a regency answering a business search is not a business, whatever the country
  calls that division.
- The run summary says what the log says. The places a contact run had no time
  to check are named in `OUTPUT`, and where most of a dataset comes from
  outside the requested area the summary gives the share and the towns rather
  than a bare count.

#### Fixed

- A search whose trade has no name of its own is judged properly. Where Google
  answers with a plain `manufacturer`, the makers filed under it were flagged
  as not the kind of place asked for. Over ten runs of such a term, 1,471 rows
  recovered and nothing else moved.
- One trade's several names are read as one — `lodging` and `lodge`, `building`
  and `builder`, `veterinary` and `veterinarian`.
- Where Google files each place under exactly one category, a short answer no
  longer throws away real results.

### \[3.0.29] - 2026-08-02

#### Changed

- An aborted or timed-out run delivers what it is holding. The Actor reads the
  platform's stop signal instead of guessing at a deadline, so everything found
  and accepted is written before the process ends. Website enrichment is
  released the moment the signal arrives rather than blocking the save, and the
  run can be resumed without re-charging a place it already delivered.
- Every run ends with a diagnosis, including the ones that end badly: a run
  that cannot get a proxy says so in plain words instead of printing a
  traceback.
- A stopped run says how many found places it never saved, and why. Places
  waiting in the enrichment queue are named in `OUTPUT` as well as in the log,
  and the per-search result limit is told apart from the charge limit.
- The run status in the Console is short, current, and never one phase behind.
- What a term means is learned from thirty of an answer's rows rather than
  twenty.

#### Fixed

- A term is quoted in messages exactly as it was typed.
- The log no longer runs its sections together.

### \[3.0.28] - 2026-08-02

#### Fixed

- A trade whose own name is short is recognised by it. The name a search term
  shares with Google's categories had to be five characters long, so `bar`,
  `spa`, `pub` and `deli` never had a trade name at all and a `tiki bar` was not
  a bar. In Japanese, Chinese and Thai, where a trade is two or three characters
  and categories carry no spaces, no answer ever named its own trade.
- A wholesale search in Japanese recovers the shops filed as a kind of
  wholesaler, a hairdresser search in Turkish no longer counts pet groomers, and
  a bar search keeps the bars filed as `tiki bar` or `bar & grill`.

### \[3.0.26] - 2026-08-02

Build 3.0.27 is the same code with corrected wording.

#### Changed

- Search terms that differ only by capitalisation or spacing are searched once.
  Google reads them as one term, so the rest bought the same places again at
  the same cost. The run says which it folded.
- A run that cannot open the Apify residential proxy explains itself — whether
  the allowance is spent, the account lacks access, or the token was revoked.
  Any unexpected error ends the same way, with the reason in `OUTPUT`.

#### Fixed

- A search term written in a script that does not space its words is recognised
  inside a category. The rule was written for the Latin alphabet, so places
  filed under the search term with a qualifier in front were marked as not
  matching — on a sector search, most of the answer.
- A run given several languages judges a place the same way whichever language
  finds it. A place is found once, and the same business could come back as the
  trade or as padding depending on which search reached it first.
- The run's advice no longer shows an internal separator inside a search term
  when several Locations were given.

### \[3.0.25] - 2026-08-02

#### Fixed

- A search for a profession keeps its specialists even where the city's own
  answer never names the profession. One city answers `doctor` with medical
  clinics and family practices and nothing filed as a doctor, so its
  paediatricians and cardiologists were flagged. The word you typed is now read
  as a trade in its own right. Flagged rows in that city fell from 21 in 120 to
  7, with none lost.

### \[3.0.24] - 2026-08-02

#### Fixed

- A run over several Locations judges each of them by its own answer. What a
  term meant was learned from every Location pooled together, so a trade that is
  a real part of one city's answer could fall below the bar once another city
  joined the run. One city went from 16 flagged rows in 120 to 4, another from 7
  to 0. The effect was strongest with two Locations; single-Location runs are
  unaffected.

### \[3.0.23] - 2026-08-02

#### Fixed

- A short trade word is read on the place's own sign. A search for `cafe`,
  `bar`, `spa` or `pub` ignored the business name entirely, so the many cafés
  Google files under `Restaurant`, `Bistro` or `Bakery` did not answer a search
  for a café.
- A name that only borrows a trade no longer answers for it. A carpet cleaner or
  a driving school can carry `doctor` in its name; where the name and the
  category disagree that plainly, the category wins. Over 21,791 places this
  removes 24 rows at a cost of 6.
- A search Google answers with only a dozen places is judged like any other.
  Below twenty results every row went out with no verdict, and
  `skipPlacesNotMatchingSearch` quietly kept everything.

### \[3.0.22] - 2026-08-02

Replaces the 3.0.12 to 3.0.21 entries.

#### Changed

- A run keeps digging where the answers are. An area full of a profession's
  specialists, or of the building trades, read as a third to a half empty and
  the run moved on while the ground still held what you asked for. Over 195
  captured answers, areas judged less than half as rich as they were fall from
  27 to one.
- Judging is faster and steadier on large runs, and the verdicts no longer
  depend on how Google spells a category or how many it gives one place.

#### Fixed

- A search for a whole profession keeps its answer. Google files the
  specialists under names sharing no word with the general practices, so they
  were flagged and a run with `skipPlacesNotMatchingSearch` on never received
  them. Such a search now recognises 98% of its real answers where it
  recognised 58%.
- The same word with a different ending is the same trade: `veterinary care` in
  a search for a vet, an electrical utility in a search for an electrician.
- A narrower kind of the trade is the trade: a cardiologist for `doctor`, an
  Italian restaurant for `restaurant`, a truck repair shop for `auto repair`.
- The same run twice returns the same rows. What a term means no longer depends
  on which Location the network answered first.
- A term whose first answer came back with almost nothing is still judged, from
  the smaller areas opened under it.
- A short search word matches the places filed under it: `shop` keeps the barber
  shops and gift shops.
- A Location means the same thing on every run. When OpenStreetMap's search was
  busy the area quietly became a box around a point, and `geoStrictMatch` kept
  or dropped the next town by chance.

### \[3.0.10] - 2026-08-01

#### Changed

- When an answer really does hold two kinds of place, the run says which two,
  once, while the search can still be changed.

#### Fixed

- A district or borough of a large city resolves to itself again. A borough
  asked for by name could fall back to a same-named village elsewhere in the
  country.
- A term that names an attribute, a language or a material no longer lets that
  count as the trade.
- The same run twice judges its rows the same way. Two equally common categories
  used to be ranked by whichever search answered first.
- The time the search spent waiting for the website pass is stated per worker. A
  14-minute run could report 98 minutes of waiting.

### \[3.0.4] - 2026-08-01

#### Changed

- A place the Apify API refuses to save is answered rather than dropped: a rate
  limit is tried once more, and a row holding a value no JSON parser accepts is
  saved without that value. What still cannot be written costs that place alone.
- A search that fails says what refused it, and the summary tells an Apify API
  refusal apart from a blocked Google request.
- A point pasted as degrees and minutes — `40°46'04.6"N 73°54'42.2"W` — is
  recognised and answered with the same `customGeolocation` line as the decimal
  form.

#### Fixed

- A place lost on its way out of the website-enrichment queue is counted and
  named in the summary. The rows went missing while the summary counted them.
- Rows the run deliberately does not judge are saved again. The verdict field
  was declared as a boolean, and writing `null` made the platform refuse the
  whole write — costing every other place found in the same map view.

### \[3.0.2] - 2026-08-01

#### Changed

- A `customGeolocation` point with `radiusKm` is matched against the circle it
  asks for, not the square around it, which reached 41% further at the corners.
  The map draws that circle too.
- An area of many drawn shapes costs the same to judge as one: a grid of 248
  circles went from 13.7 ms a place to 10 µs, with identical verdicts.
- `matchesSearchTerm` is on every row, `null` where the term names a class of
  business rather than one kind of place.
- A run over a drawn area is told to switch on `geoStrictMatch` rather than to
  name a place it never named; a strict run names the towns its results were in.

#### Fixed

- A place whose own name carries the trade, as a word rather than a run of
  letters, is recognised as that trade whatever Google filed it under.
- Every count in the summary is a count of saved rows. A place Google published
  no location for was being called inside the area.

### \[3.0.0] - 2026-07-31

#### Added

- `matchesSearchTerm` on every row: whether the place is the kind of place the
  search term asked for. It is decided from the categories Google returns for
  the term, so there is no list to maintain and it works in any language. On
  hand-labelled results from ten markets in six writing systems it keeps 99.8%
  of the places that match and marks 94.6% of those that do not. A term that
  names a class of business rather than one kind of place carries `null`, and
  none of its rows is removed.
- `skipPlacesNotMatchingSearch` drops the marked rows instead of saving them.
  Off by default; the field is on every row either way. Dropped rows are not
  charged and do not count towards the number of places to extract, so the ask
  is filled with places that match.
- `categoryId` — Google's own id for a category, such as `dental_clinic` or
  `jewelry_store`, identical in every market whatever language the names come
  back in, so an export can be filtered without reading the local words.

#### Changed

- A map area opened during a search now searches itself instead of repeating
  the whole region's query: 22% more places of the searched trade for the same
  number of searches.
- The requested area is split whatever its size, so a large city or region is
  covered rather than read from a single map view.
- A search stops when new places run out rather than when the number is filled.
- The website pass runs alongside the search, so a run takes as long as the
  slower of the two rather than both in sequence.
- Towns, districts and other map features Google returns to a business search
  are recognised by their id and no longer saved as places.
- A place whose own name carries the trade is recognised as that trade whatever
  Google filed it under; a great many real shops are filed under the generic
  `store`.
- Every count in the end-of-run report comes from saved rows, and a dropped
  place is counted once rather than once per map view.
- A run without strict matching whose rows came mostly from around the area
  reports that share and names the towns; a strict run names the towns its
  dropped results were in.
- Places dropped for having no coordinates are reported separately from places
  dropped for being outside the area.
- One framed block per phase in the log, with the place count and run time in
  the **Result** header.
- Network failures are reported in plain words instead of curl's text.
- A resolved Location reports its width in kilometres and whether it came from
  a boundary or a box.
- Rows that do not match the search term have their own colour on the map.

#### Fixed

- A `customGeolocation` point with `radiusKm` is matched against the circle it
  asks for rather than the square around it, which reaches 41% further at the
  corners.
- A resumed run no longer saves, or charges for, a place it already saved.
- A run migrated by the platform keeps what it learned for each search term and
  goes on judging rows afterwards.

### \[2.0.25] - 2026-07-27

#### Fixed

- A city matched as a point is searched as the city, not as a square.
  OpenStreetMap holds a city as both a labelled point and an outline, and a name
  search often matches the point; the Actor then fell back to a placeholder box
  about 35 km on a side — the same square for every city on Earth. The real
  outline is now found and used, and it also frames the search, so a city wider
  than the square is no longer searched only in its middle. This fixes whole
  countries at once: no Australian council boundary appears in an address, so
  every Australian city had been searched as that square.
- A district inside a city can no longer stand in for the city. In countries
  that divide a city into wards, the nearest unit above the centre is one ward
  inside it — one wide city was being searched as a 6 km box.
- The city-name test works in every language. A city is rarely spelled exactly
  like its own boundary: the qualifier may lead or follow, the name is often
  inflected, and names outside the Latin alphabet compared as empty so nothing
  matched. Names are now compared in the run's language and in the original,
  and agreement in either settles it. Over small towns in about fifty
  countries, this is a dozen towns keeping their boundary rather than losing
  it.

### \[2.0.22] - 2026-07-25

#### Fixed

- Short runs no longer spend a third of themselves waiting on a counter. A run
  that finished just after saving spent 5 to 9.5 seconds doing nothing, on runs
  of 13 to 19 seconds, waiting for Apify's row count to catch up with the rows.
  The check now asks about the rows, which answers immediately. It also could
  report fewer places than it saved.
- A pin on the map opens the place, not a search for it. Rebuilding the link
  from coordinates could land on a neighbour, or on a list of results.

### \[2.0.21] - 2026-07-25

#### Changed

- The map of the results no longer stops at 20,000 places. It budgets how heavy
  the page is rather than counting pins: roughly 54,000 places of typical lead
  data now fit, and around 260,000 sparser rows.
- The run log says what the map left off.
- **Action needed** tells you again to move a location out of a search term.

### \[2.0.20] - 2026-07-25

#### Changed

- The map search no longer waits for business websites. With contact enrichment
  on, a search of one map area was held open until every place it found had had
  its website checked, so coverage advanced at the speed of the slowest sites —
  a statewide run reached 36 of the 99 areas it had identified. Website checks
  now run alongside the search, and the website pass takes the top result of
  every area before the second result of any of them, so a run that runs out of
  time has covered the area evenly. What is saved is unchanged: a place is only
  saved once its website has been checked. Runs that also request reviews, or
  that keep only places with an email, are unaffected.
- Contact pages are fetched direct, with the whole site timeout. Retrying one
  over the proxy returned a usable page 3% of the time and cost every direct
  fetch most of its time. Seconds per email recovered from a contact page fell
  from 17.4 to 11.9.
- Retrying a homepage that answered but published no contacts is gone; it
  recovered contacts once in 1,351 attempts. The homepage fallback for sites
  that do not respond at all is unchanged, and succeeds 41% of the time.
- Business websites are asked for a compressed page: 8% faster per page across
  77 sites, byte-for-byte identical content.
- `searchPagesFetched` and `searchPagesSaved` are now
  `searchXhrTemplatesFetched` and `searchXhrTemplatesReused`, which is what they
  counted.

#### Fixed

- Businesses with no storefront no longer carry a made-up location. Google gives
  them a placeholder coordinate that several unrelated firms share; between 9%
  and 27% of rows in a typical lead run were affected. Such rows now arrive with
  `locationUnverified: true` and no `location` at all, the same rule the address
  fields already followed.
- **Action needed** no longer tells you to put the service in the search terms
  and the city in Location when that is what you did.

### \[2.0.19] - 2026-07-24

#### Fixed

- A Location such as `Kolkata, IN` or `Medellín, CO` is read as the country, not
  as the US state that shares the abbreviation. The seed used to land in the
  United States, the city's boundary was lost, and the proxy could not be
  matched to the target country. Spelling out `City, IN, USA` still selects the
  US state.

### \[2.0.18] - 2026-07-23

#### Fixed

- City-boundary recovery works the same way in every country. It picked the
  boundary by a fixed map zoom, which lands on a municipality in one country and
  a state in another; it now reads the city's own place hierarchy.

### \[2.0.17] - 2026-07-23

#### Fixed

- Boundary recovery no longer widens a neighbourhood into a state. Recovery runs
  only for a city or town, and the area it accepts must be municipal in scale.

### \[2.0.16] - 2026-07-23

#### Fixed

- The exact city boundary is found even when the search returns only a point.
  For some cities OpenStreetMap answers with the point and a placeholder box, so
  the run treated a 35 km square of countryside as the city. The boundary is now
  looked up by location, and accepted only when it is a real administrative area
  of city or county scale that encloses the point.

### \[2.0.15] - 2026-07-23

#### Fixed

- A run that hits `maxTotalChargeUsd` stops cleanly instead of paying out a
  quiet tail. Requests already in flight ran their full proxy-retry ladder,
  minted fresh sessions and opened second looks after the run had decided to
  stop — all proxy bandwidth bought for rows that could no longer be saved.
  Retries, fresh sessions and extra passes now bail out at once; the first,
  already-open request of each task is left to finish.
- The wind-down reports the running total and how many tasks are still
  finishing, and agrees with the summary. It used to report skipping zero queued
  tasks and then go silent.

### \[2.0.14] - 2026-07-20

#### Changed

- `customGeolocation` is read in whatever form you drew it: `FeatureCollection`,
  `Feature`, `GeometryCollection`, a plain array of any of those, a `geometry`
  wrapper, and the whole thing as a JSON string. `MultiPoint` seeds one area per
  point, and a `LineString` that closes on itself is read as the polygon it
  draws. Several shapes in one collection each become a search area.
- Coordinates pasted latitude-first are corrected when that is provable — a
  value past ±90 in the second slot can only be a longitude — and left alone
  when it is genuinely ambiguous.
- When an area cannot be read, the run says so and names what is accepted,
  instead of blaming the Location field.

#### Fixed

- Only a bare geometry was accepted before, so pasting what geojson.io, QGIS,
  Mapbox or My Maps exports produced no search area at all and the run finished
  in seconds having saved nothing.

### \[2.0.13] - 2026-07-18

#### Changed

- Multi-city runs stop paying for searches that no longer find anything. Where
  a search stops paying was measured per city, so every city re-learned the same
  lesson; it is a property of the search term and is now measured once across
  the run. On a many-city run this cut total searches and proxy traffic by
  roughly half for a 3% change in places found.
- Geocoding setup for many-Location runs is about twice as fast: each Location
  takes one request instead of two. On a 50-Location run, setup drops from about
  120 seconds to 65.
- The end-of-run writes — resume state, results map and `OUTPUT` — run
  concurrently, so the tail costs the slowest single write rather than their
  sum. About 12 seconds on a large run.

#### Fixed

- Multi-city runs no longer freeze on area membership. Measuring a place's
  distance to an area walked every segment of every requested outline, and a
  large city boundary has thousands, so one membership pass could burn 11
  seconds of CPU — and a frozen run cannot fire its own request timeouts, which
  surfaced as a wave of proxy errors that were really the run locked up. Same
  verdicts, same billing; a 50-town pass drops from 11 seconds to 40
  milliseconds.

### \[2.0.12] - 2026-07-17

#### Fixed

- A city search asks Google for the city. Asked for a map at a given zoom,
  Google frames four times the ground the Actor believed it did, so a city
  resolving to zoom 10 was searched through a 95 km map view rather than 24 km.
  On one city, 53% of the results landed outside the area the Actor thought it
  had asked about. Zoom is now read off what Google actually frames: places
  inside the city unchanged at 208, places more than 24 km away down from 50 to
  18\. Nothing else moves — what counts as inside an area, how the grid is laid
  and where it splits are exactly as before.

### \[2.0.11] - 2026-07-17

#### Fixed

- A strict run no longer keeps searching long after it has everything. The
  search decided where to look next by counting every place it had been shown,
  dropped ones included, so a strict search answering with 182 places and
  keeping 2 was read as having found 85. One run spent 100 searches on the
  deepest levels to keep 3 places. Saved is now the only thing the search ranks
  by: 114 searches down to 16, a fifth of the data, the same places. Runs
  without `geoStrictMatch` were never affected.

### \[2.0.9] - 2026-07-17

#### Changed

- A smaller map area no longer downloads the places it was just given. Google
  ranks an answer outward from the centre, so each split opened on the places
  its parent had already returned. A split now asks Google to start past that
  head: a fifth fewer places downloaded for the same results.
- What a search must find to be worth running is measured rather than assumed.
  The same search came back with 186 KB, 246 KB and 460 KB across three runs, so
  an area whose answers come back big now has to find proportionally more to be
  worth opening.

### \[2.0.8] - 2026-07-17

Replaces 2.0.3 through 2.0.7.

#### Changed

- The search opens the most promising map area next, and stops when searching
  stops paying. It used to divide every area into four down to a fixed limit,
  whatever the ground held: on one run, a term with 56 places to find in that
  city found its last on search 44 and then ran 118 more finding nothing — 41%
  of the whole run. Areas are now ranked by what the area they came from
  actually found, so if the most promising area left will not pay for its
  search, nothing else will.

  | | places | time | data | searches |
  |---|---|---|---|---|
  | before | 710 | 350 s | 106 MB | 860 |
  | now | 593 | 57 s | 12 MB | 63 |

- A map area's shape is measured rather than assumed, and the seed goes in
  first, with a grid following only if the seed asks for one.

- A country-scale grid buys what its budget affords.

### \[2.0.2] - 2026-07-16

#### Fixed

- A run could spend its whole budget dividing the map instead of searching it.
  Whether Google had truncated an area was judged against a bar that moved with
  the run's remaining budget, and the answer was read down to that budget too,
  so every area returned exactly the bar and every area looked truncated. The
  bar is now a property of Google's answer and does not move; the whole answer
  is read, since one request returns all of it either way. A run asking for 20
  places in one city returned 15 after 342 requests and timed out with 59 areas
  queued; it now returns all 20 in 27 seconds and 22 requests. A capped
  multi-city run: same places, half the wall clock, 220 requests down to 28.
  Runs whose budget is never reached are unaffected.

### \[2.0.0] - 2026-07-16

Runs are two to four times faster and return far more places. On an identical
input: 43% more places in 26% less time.

#### Changed

- Deciding whether a place falls inside the requested area no longer starves the
  run of network time. It was a ray cast over every vertex of the boundary —
  sixteen thousand of them for a state-sized region, 5.11 ms per place against
  0.17 ms to parse a whole search response — and it ran where no worker could
  send or receive a byte. Now 0.004 ms per place, with an identical answer. On
  default settings this alone took a run from 216 to 772 places per minute and
  cut proxy errors by 92%.
- Map areas are split on what Google truncates rather than on what looks new.
  Novelty measures what has already been downloaded, not what an area still
  holds, so whichever area was searched first left the next looking empty and
  the same input returned 683 places one run and 1,191 the next. Places per run
  rose 110%, and the run-to-run spread fell from 1.74× to 1.23×.
- One request fetches what six used to. Google's own page asks for 20 results at
  a time and every published scraper copies it; asked for 250, Google answers
  with everything it holds for the area. 25% more places for the same wall
  clock, and each place costs less.
- More rows means a larger bill for the same input. `maxCrawledPlacesPerSearch`
  and `maxTotalChargeUsd` bound every run exactly as before.
- Nothing about the output shape, the fields, the strict-area rules or the
  billing events changed — only how much of the map a run manages to look at.

#### Fixed

- A page size above 199 silently reset itself to 20 and paginated to a nonsense
  offset.
- The counter reporting how many saturated areas went unsplit was itself gated
  on novelty, so it could not see the areas the novelty rule blocked.

### \[1.6.120] - 2026-07-16

Internal changes only.

### \[1.6.119] - 2026-07-16

#### Added

- Every place carries its photo as a usable image, and bookable venues carry
  their booking link, from the same search response.

### \[1.6.118] - 2026-07-16

#### Fixed

- A city whose boundary reaches distant islands is framed on the city, not on
  the ocean between them.

### \[1.6.117] - 2026-07-16

#### Fixed

- A language typed by name, or in its own script, no longer breaks the search.
  **Additional languages** accepts a language's name and maps it to the right
  code.

### \[1.6.116] - 2026-07-16

#### Changed

- Each worker keeps one warm residential exit and reuses it across searches:
  fewer network errors and faster searches.
- A subdivided map area no longer re-fetches a thin first page on a fresh
  session.

### \[1.6.115] - 2026-07-16

#### Fixed

- A map area that runs out of good proxy exits gets another try instead of
  being dropped.

### \[1.6.114] - 2026-07-16

#### Fixed

- Runs over many large areas no longer freeze. A run searching a dozen
  city-sized areas at once used to stall.
- Large runs use the extra workers they were already asking for.

### \[1.6.111] - 2026-07-14

#### Changed

- A run that searched the wrong place says so: when a Location resolves to
  somewhere you did not mean, the run tells you.

#### Fixed

- A run without strict matching is no longer told to turn strict matching off.

### \[1.6.109] - 2026-07-14

#### Fixed

- When Google reads a search as an address and answers with a single place, the
  search is asked again.

### \[1.6.108] - 2026-07-14

#### Fixed

- Distance to the search area is measured against the area, so the guard that
  drops far-away junk works for country searches again.

### \[1.6.107] - 2026-07-14

#### Changed

- Searching a whole country searches where its businesses are, rather than
  spreading evenly over land nobody lives on. A country is bounded by its
  border, not by a rectangle around it.

#### Fixed

- A Location of `USA` searched nowhere in particular.

### \[1.6.104] - 2026-07-14

#### Changed

- Strict means strict: a strict run never saves places from outside the search
  area. The fallback rows are gone.
- An empty area is abandoned rather than searched to the end.

### \[1.6.102] - 2026-07-14

#### Fixed

- A small run stops being a coin flip. The same search returned 5 places one
  time and 19 the next.

### \[1.6.100] - 2026-07-14

#### Fixed

- A city with an accent in its name is no longer searched as its whole
  province. Names are compared without their accents, since the geocoders do
  not agree with each other about them.
- The fallback no longer answers with a building when it does not know the
  place.

### \[1.6.98] - 2026-07-14

#### Removed

- Nine advanced settings — places per map view, subdivision depth and the rest.
  The Actor tunes itself.

### \[1.6.97] - 2026-07-14

#### Added

- `keepUnverifiedLocations`: keep businesses Google publishes no address for.

### \[1.6.96] - 2026-07-14

#### Changed

- A map view is read in waves rather than page by page.

### \[1.6.95] - 2026-07-14

#### Fixed

- Big runs stop queueing. Covering an area means many more searches than
  splitting one seed did.

### \[1.6.94] - 2026-07-14

#### Changed

- The same places for half the time and half the cost: the second look
  introduced in 1.6.92 was paying full price.

### \[1.6.93] - 2026-07-14

#### Fixed

- Sprawling cities are searched properly. A city that reaches out in arms was
  searched as if the arms were empty.

### \[1.6.92] - 2026-07-14

#### Changed

- The search covers the city, and a run stops depending on luck. The same input
  used to find 130 places or 300.
- A place Google leaves out of one answer is asked for again.

### \[1.6.91] - 2026-07-14

#### Changed

- The map is cut where Google is holding places back, so more places inside the
  search area for the same money.
- A search area no longer costs a search page of its own.

### \[1.6.89] - 2026-07-13

#### Fixed

- A long search term could lose a whole search area to the retry meant to save
  it.

### \[1.6.87] - 2026-07-13

#### Fixed

- A map area could report no places while Google was handing them over.

### \[1.6.86] - 2026-07-13

#### Changed

- An oversized boundary is simplified rather than discarded.
- The description of `additionalLanguages` says what it does: a second language
  finds places the first never returns.

#### Fixed

- A city that shares its province's name searched the whole province.
- The run diagnosis no longer claims dropped places had no coordinates when
  they did.

### \[1.6.85] - 2026-07-13

#### Fixed

- Strict mode no longer saves places from neighbouring towns. A province that
  shares its capital's name let other towns in.
- The biggest metropolises get their real boundary.

### \[1.6.84] - 2026-07-13

#### Added

- An interactive map of the results, written with every run.

#### Changed

- A place is judged against the requested place, not only against its polygon.
- Results hundreds of kilometres away are dropped rather than saved.
- Addresses are no longer invented for businesses that have none.

### \[1.6.83] - 2026-07-13

#### Changed

- Reviews no longer log two lines per place.

### \[1.6.82] - 2026-07-13

#### Fixed

- Obfuscated addresses such as `(at)` and `[dot]` no longer slow a site read to
  a crawl.

### \[1.6.81] - 2026-07-12

#### Changed

- The run log is organised into sections: **Setup**, **Run plan**, **Search**,
  **Result**.
- Website enrichment statistics are logged as one readable block.
- Run diagnostics are logged once, at the end, instead of twice.
- A retry line reports what actually failed — a timeout, a proxy error, an HTTP
  status.

### \[1.6.80] - 2026-07-09

#### Fixed

- Website enrichment keeps homepage contacts it had already found.
- Extra phone numbers are deduplicated across local and international formats.
- Facebook links no longer pick up non-profile paths.

### \[1.6.79] - 2026-07-09

#### Changed

- The README follows Apify Store guidance more closely.
- Contact-page extraction reads the same slice size as the extended homepage
  pass.
- Font-licence addresses found in stylesheets are no longer collected as
  contacts.

### \[1.6.74] - 2026-07-08

#### Changed

- Finished places stream to the dataset as soon as they are ready rather than
  waiting for the batch.
- Website enrichment fetches the homepage first and only then the pages it
  links to.
- Page downloads are capped, so a large page cannot dominate a run.

### \[1.6.73] - 2026-07-06

#### Fixed

- Automatic proxy country selection for special territories.

### \[1.6.72] - 2026-06-29

#### Fixed

- Raw `placeIds` are resolved again.

### \[1.6.71] - 2026-06-29

#### Changed

- The strict-area documentation says plainly what strict mode does, what a
  fallback row is, and what a zero-place diagnostic row is.

### \[1.6.70] - 2026-06-27

#### Changed

- `geoStrictMatch` and `customGeolocation` descriptions say what each does.
- Strict-fallback messages are worded for a high-volume run.
- The structured `county` field is labelled for what it is.

#### Fixed

- An invalid hidden `proxyConfiguration` is ignored with a clear message.

### \[1.6.67] - 2026-06-24

#### Fixed

- The final summary for direct URL and Place ID runs, and for runs skipped
  early.

### \[1.6.66] - 2026-06-24

#### Added

- One clearly marked diagnostic row for a run that saves zero places, and
  `totalPlaces` and `diagnosticRows` in `OUTPUT` so an export can tell them
  apart.

### \[1.6.65] - 2026-06-24

#### Changed

- The log names things a reader recognises instead of internal task keys.

### \[1.6.64] - 2026-06-24

#### Added

- A **Run plan** block spelling out the requested limits, and a **Result
  summary** with saved places and strict-area counts.

#### Changed

- Website enrichment diagnostics read as information rather than warnings.

### \[1.6.63] - 2026-06-24

#### Fixed

- Duplicate warnings for a run whose search terms include a city or country.

### \[1.6.62] - 2026-06-24

#### Added

- An **Action needed** section summarising what to change.

#### Changed

- Run warnings give a direct next step instead of a low-level reason.

### \[1.6.60] - 2026-06-24

#### Added

- A rescue path for `geoStrictMatch=true` searches that would otherwise save
  nothing. Rescued rows are marked `geoStrictFallback=true`. If at least one
  in-area place is saved, strict mode stays strict.

### \[1.6.58] - 2026-06-24

#### Changed

- Startup subdivision is adaptive for strict-area and filtered searches, and
  stays eager for broad ones.

### \[1.6.52] - 2026-06-24

#### Added

- Budget checks before optional website contact enrichment.
- Caps on oversized input arrays, and memory limits so the Actor cannot be
  started too small to run.

### \[1.6.51] - 2026-06-21

#### Fixed

- Reviews are read from Google's own reviews endpoint, and pagination follows
  it correctly for high `maxReviewsPerPlace` values.

### \[1.6.50] - 2026-06-21

Internal build.

### \[1.6.49] - 2026-06-21

#### Changed

- Reviews are read in batches, and a slow place no longer holds up the rest. A
  place that returns no reviews is still retried once on a fresh exit.

### \[1.6.48] - 2026-06-21

#### Changed

- A large multi-Location run starts every Location at once instead of working
  through them in order.
- Progress is reported after results pass the local filters.

### \[1.6.47] - 2026-06-21

#### Fixed

- Many-Location runs no longer overrun the OpenStreetMap geocoder's rate limit,
  so strict mode keeps its exact boundaries.

### \[1.6.46] - 2026-06-15

#### Fixed

- Task bookkeeping after the 1.6.45 subdivision change.

### \[1.6.45] - 2026-06-15

#### Changed

- Automatic subdivision requires saturation inside the resolved search area, so
  a strict multi-Location run makes fewer raw requests.

### \[1.6.44] - 2026-06-15

#### Fixed

- In a multi-Location run, a place outside one city but inside another is no
  longer counted twice against strict-mode statistics.

### \[1.6.43] - 2026-06-15

#### Fixed

- Nearby out-of-area results no longer drive strict-area subdivision. A map
  area counts as saturated only on results inside the area. Strict filtering
  itself is unchanged.

### \[1.6.42] - 2026-06-15

#### Changed

- The per-place review wait is shorter for small review limits, and a bad
  review session is abandoned at once.

### \[1.6.41] - 2026-06-15

#### Fixed

- A per-place timeout for review extraction, so one slow place cannot hold a
  task open.

### \[1.6.38] - 2026-06-12

#### Fixed

- Pages hosted on a shared platform are recognised as such, and the website
  cache no longer hands two places the same contact object.

### \[1.6.37] - 2026-06-12

#### Changed

- Automatic subdivision focuses on the resolved search area, which helps most
  where a rectangular split reaches well outside it.

### \[1.6.36] - 2026-06-12

#### Fixed

- The legacy `placeMinimumStars` warning fires for any saved task that still
  sends it.

### \[1.6.35] - 2026-06-12

#### Removed

- The public controls for post-fetch category, exact-title and website filters.
  Saved tasks that still send them keep working. `skipClosedPlaces` and
  `geoStrictMatch` remain.

### \[1.6.34] - 2026-06-11

#### Changed

- The repeated reverse-geocoder warning says what it means.

### \[1.6.33] - 2026-06-11

#### Changed

- Optional address backfill is quieter, and its counters are in the run
  statistics.

### \[1.6.32] - 2026-06-11

#### Fixed

- Short state codes in a Location are matched as words rather than as letters
  inside another word.

### \[1.6.31] - 2026-06-11

#### Fixed

- Bare US state abbreviations no longer capture global queries.

### \[1.6.30] - 2026-06-11

#### Changed

- Obvious table headers pasted into Location, such as `City State`, are
  ignored, and common US shortcuts such as `Irvine CA` are expanded.

### \[1.6.29] - 2026-06-10

#### Changed

- Exports without strict matching are more even under per-search limits. Strict
  mode is unchanged and out-of-area rows are not hidden.

### \[1.6.28] - 2026-06-10

#### Added

- A warning when a search term repeats the Location, and one when the geocoder
  returns several places of the same name.

#### Changed

- Location lookup falls back sooner rather than retrying a rate limit.

### \[1.6.27] - 2026-06-10

#### Changed

- Less wasted pagination in focused map areas.
- Contact pages that differ only by an anchor are fetched once.

#### Added

- Copied Google Maps search URLs that encode the map view are accepted.

### \[1.6.26] - 2026-06-10

#### Changed

- Pricing events are detected through Apify's official interface, and expensive
  website and review work is checked against the remaining budget first.

### \[1.6.25] - 2026-06-10

#### Changed

- `geoStrictMatch` sits directly under the Location fields, with help text
  saying what it applies to.

### \[1.6.24] - 2026-06-10

#### Changed

- One public `locationQueries` field replaces the two visible location inputs.
  `locationQuery` stays as a hidden compatible field, and the structured
  geolocation fields are ignored when `locationQueries` is given.

### \[1.6.23] - 2026-06-10

#### Added

- `locationQueries`: the same search terms across several Locations, with
  `maxCrawledPlacesPerSearch` applying per term per Location and one shared
  deduplication set.

#### Changed

- Proxy country selection stands down when several target countries are
  detected.

### \[1.6.21] - 2026-06-10

#### Removed

- The public `websiteFilter` and `skipPlacesWithoutEmail` fields. Saved tasks
  that still send them keep working.

### \[1.6.18] - 2026-06-05

#### Added

- `contactsFilterEmailsByWebsiteDomain`, on by default, and website-enrichment
  counters in `OUTPUT.searchStats`.

#### Changed

- Email domain matching is less brittle on real small-business sites.

### \[1.6.17] - 2026-06-04

#### Changed

- Rolled back the 1.6.16 strict-mode behaviour. `geoStrictMatch=true` still
  drops places whose coordinates fall outside the area.

### \[1.6.16] - 2026-06-04

#### Changed

- Homepage extraction decodes more ways of hiding an address in the page.
- Where the homepage has no email, up to five contact pages are read, binary
  files are skipped, and a failed deep URL falls back to the site's root.

### \[1.6.15] - 2026-06-03

#### Changed

- `maxCrawledPlacesPerSearch` applies to each accepted search URL
  independently. Keyword searches keep the per-term limit.

### \[1.6.14] - 2026-06-03

#### Changed

- Input help and README describe the search-URL support, and the acceptance log
  line renders as plain text.

### \[1.6.13] - 2026-06-03

#### Fixed

- A Google Maps search URL is searched at the size of the view it encodes.

### \[1.6.12] - 2026-06-03

#### Added

- `startUrls` accepts copied Google Maps search result URLs, searched in the
  map view they carry, with counts reported in `OUTPUT`.

### \[1.6.11] - 2026-06-03

#### Added

- `stoppedByChargeLimit` and `chargeLimitEvent` in `OUTPUT`, so a run that
  stopped at its spending limit says which event reached it.

### \[1.6.10] - 2026-06-03

#### Changed

- Contact billing falls back to the previous events until the new pricing takes
  effect on 2026-06-17.

### \[1.6.9] - 2026-06-03

#### Fixed

- Add-on charging no longer depends on a pricing guard that could be absent.

### \[1.6.8] - 2026-06-03

#### Changed

- Website email and social add-ons are charged as one combined event; reviews
  are charged per review; the base per-place event is unchanged.

### \[1.6.7] - 2026-06-02

#### Changed

- A sticky search session fails fast on a long connection timeout instead of
  waiting it out.

### \[1.6.6] - 2026-06-02

#### Changed

- Suburbs and neighbourhoods are matched against their exact boundary; broad
  regions keep the faster box test.

### \[1.6.5] - 2026-06-02

#### Changed

- `customGeolocation` polygons are matched exactly, without the previous
  adaptive tolerance.

### \[1.6.2] - 2026-06-02

#### Changed

- `geoStrictMatch=true` refuses to run when the Location gives no area to check
  against. A point still adds its context to the search.

### \[1.6.0] - 2026-06-02

#### Changed

- A search carries the resolved Location in the query, which cuts nearby
  out-of-area results before any filtering.

### \[1.5.65] - 2026-06-01

#### Added

- The `geoStrictMatch` switch, off by default, and `insideSearchArea` on every
  row where an area and a coordinate are both known.

### \[1.5.64] - 2026-05-31

#### Fixed

- Subdivision stops for child areas that hold only out-of-area places.

### \[1.5.63] - 2026-05-31

#### Added

- A full drop breakdown in `OUTPUT` for a run that saved nothing.

### \[1.5.62] - 2026-05-31

#### Fixed

- One bounded seed-level split is allowed again, and search tasks are
  deduplicated as they are queued.

### \[1.5.61] - 2026-05-31

#### Changed

- Subdivision is tighter where results are mostly out of area, and a soft
  timeout guard stops the search before the platform's hard timeout.

### \[1.5.60] - 2026-05-30

#### Changed

- The input form explains how to get exact Google Maps URLs, and separates raw
  Place IDs from URLs that contain one.

### \[1.5.59] - 2026-05-30

#### Changed

- Changelog headings use Apify build revisions.

### \[1.5.58] - 2026-05-30

#### Added

- `query_place_id` and `q=place_id:…` URLs without a search term are resolved,
  and a direct place page is replayed against Google's own endpoint.

### \[1.5.57] - 2026-05-30

#### Changed

- An invalid Place ID is rejected before any request is made.
- `startUrls.userData` is preserved on dataset rows.

### \[1.5.52] - 2026-05-30

#### Fixed

- Broad state and country searches carry the resolved Location text.
- Proxy session identifiers match the pattern Apify Proxy accepts.

### \[1.5.29] - 2026-05-29

#### Changed

- A search area tries several fresh proxy sessions before giving up, and a run
  with failed areas reports `PARTIAL` rather than success.

### \[1.5.24] - 2026-05-25

#### Fixed

- Email-only lead runs apply the requested limit to the rows that survive the
  filter, and say so when the filter is used without website enrichment on.

### \[1.5.22] - 2026-05-24

#### Changed

- `maxCrawledPlacesPerSearch` is enforced across concurrent searches rather than
  per search in isolation.
- A run with nothing to search writes `INPUT_NEEDS_ATTENTION` and says what is
  missing, and search terms without a Location get their own warning.

#### Added

- Strict runs report out-of-area counts in `OUTPUT`.

### \[1.5.20] - 2026-05-23

#### Changed

- `maxReviewsPerPlace` supports up to 1,000 reviews per place, read through
  Google's paginated review feed with author, text and rating kept together.
  Large limits use more requests and take longer.

### \[1.5.10] - 2026-05-17

#### Fixed

- Fake addresses are no longer built out of the word "at" in a page.
- Registrar, CMS and CDN addresses are rejected, as are addresses published at
  the literal `@www.` form of a host.
- Subdivision no longer cascades into empty space, and seeds are split ahead
  when workers are idle.
- A one-shot request fails fast on a proxy-anchored error.

### \[1.4.0] - 2026-05-13

#### Added

- `maxReviewsPerPlace`: opt-in per-place review extraction.

#### Fixed

- Duplicate entries in `additionalInfo`.
- Compound-city addresses in Turkey and some other markets are split correctly.

### \[1.3.0] - 2026-05-05

#### Changed

- The residential proxy is used for Google requests only. Business websites and
  geocoding go direct from the worker, so proxy traffic is spent where it is
  needed.

### \[1.2.0] - 2026-05-05

#### Changed

- The memory floor is 128 MB and the default 512 MB, so a small run is cheaper.
  A light run peaks at 80 MB and a medium one with full website enrichment at
  109 MB.

### \[1.1.0] - 2026-05-04

#### Fixed

- Places from the wrong country are dropped. A single run had been returning
  places from four countries and several unrelated regions.

### \[1.0.0] - 2026-05-03

First public release. Google Maps places without a browser or an API key.

#### Added

- Search by term and Location, or by pasted Google Maps URL or Place ID.
- Quad-tree map subdivision, multi-zoom expansion and multi-language passes for
  coverage.
- About 46 fields per place.
- Post-fetch filters, an optional website-contacts add-on, strict area
  matching, and resumability across platform migrations.
- Pay-per-event pricing: one event per saved place, one for a place with
  contact details, one per review.
