# Google Maps Scraper Alternative - Local Business Leads by City (`tidytools/places-database`) Actor

Business lead lists for any city, box or country from the open Overture Maps places data: name, category, address, coordinates, website, phone, role emails (info@) and socials. No proxies, no blocking. $1/1,000 places.

- **URL**: https://apify.com/tidytools/places-database.md
- **Developed by:** [Yukai Lin](https://apify.com/tidytools) (community)
- **Categories:** Lead generation, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 places

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### What does Places Database do? Search businesses → get email, phone and social links in one run

- **You give:** a city and a business type, e.g. `Austin, US` + `dentist` (or `München, DE` + `Zahnarzt`).
- **You get:** one row per business with name, category, address, coordinates, website, phone (in +E.164 form), role e-mail addresses (info@, contact@) and social links, from the open **Overture Maps places dataset**. Select **+ Contact enrichment** to read the business website for more emails, phones and social profiles in the same run.
- **You pay:** **$1 per 1,000 places** returned, no start fee. Locations that are not found, runs that match nothing, filtered-out places and duplicates are free. 20 places cost $0.02.
- **Good to know:** it is a snapshot of an open dataset, not a live map. In big cities roughly half of the records were last updated more than a year ago; the *Max source age* option keeps only recent ones (see [What to expect](#what-to-expect-from-the-source-data)).

No map website is scraped, so there are **no proxies, no CAPTCHAs and no blocking**; a city takes under a minute to a few minutes.

### How to use it: get a lead list

1. In **Cities or areas**, enter one city per line with its country code: `Lisbon, PT`, `Austin, US`.
2. In **Categories**, enter the business type: `dentist`, `restaurant`, `lawyer`, `hotel`... (English, Overture names such as `dental_clinic`, or common words in German, French, Spanish, Portuguese, Italian, Dutch, Chinese and Japanese). Leave empty for every business.
3. Set **Max places** (the run never returns or charges more). For website contacts in this run, tick **Only places with a website** and choose **+ Contact enrichment** under **Add contacts or company details**. Choose **Email only** if a phone or social link alone should stay free.
4. Click **Start**, then export the dataset as CSV, Excel or JSON. The default overview includes `contactEmails`, `contactPhones`, `contactSocials` and the three freshness fields. The **directory** view retains the original overview columns; **full** contains the source and enrichment details.

### What else it does

- 🏙️ **City, box or country**: `Austin, US`, a bounding box `13.30,52.48,13.45,52.56`, or a country code. About 290 major cities use their whole **urban area** (Austin includes Round Rock and Pflugerville, Berlin includes Potsdam); every other place is cut out along its real boundary (looked up with OpenStreetMap Nominatim). Each row has its own `city` field, so you can filter to the city proper.
- 🏷️ **Category filter**: plain words (`dentist`, `lawyer`, `car repair`) are mapped to Overture categories such as `dental_clinic`, `attorney_or_law_firm`, `automotive_repair`; Overture names work directly. Plurals and spaces are fine, and a parent category (`food_and_drink`, `health_and_medical`) includes everything under it. If nothing matches, the free `no_results` row and the log list the most common categories in your area. A category the Actor cannot read (for example a word in a language it has no translation for) is refused instead of being ignored, so you never get, and pay for, every business in the city by mistake. Overture's `plumbing` category also contains plumbing supply shops, and `lawyer` includes every kind of legal service.
- 🔗 **Chains last**: when one name has many branches (Starbucks, Droga Raia), the first branch is listed with the distinct businesses and the other branches follow, so a short list is not ten copies of one chain. All branches are still returned when *Max places* allows.
- ✅ **Quality gate**: confidence of at least 0.85 by default (Overture's score that the place exists), places the source marks as permanently closed removed.
- 🕒 **Freshness filter**: *Max source age in months* (for example 12) keeps only places whose source record was updated recently. Older records are likelier to be closed or moved. The run summary counts how many returned places are older than 12 months.
- 🕒 **Freshness per row**: `sourceUpdated` is the date in the Overture source, `retrievedAt` is when this Actor read the record, and `lastVerifiedAt` is the recorded time of a successful website read by this Actor's contact enrichment. Company classification runs through a separate Actor that does not return a website-check time, so its `lastVerifiedAt` stays null. `lastVerifiedAt: null` means no verifiable website-check time is available; none of these dates proves the business is still operating.
- 💬 **Clear answers when nothing matches**: a city, category or filter with no data ends with a free `no_results` row that says why (no data in the area, below your confidence, the filters, a category name that does not exist with the most common ones nearby), instead of an empty table.
- 🧹 **Duplicates removed**: same name and address, name and phone, name and spot (about 11 m), or same website, postcode and name start. Duplicates are never charged.
- 📇 **Business fields only**: no person names are extracted. E-mails are **role addresses only** (info@, contact@, sales@...) unless you switch on personal addresses yourself.
- 🔎 **Filters**: only places with a website, phone or e-mail; per-city caps; best-scored places first.
- ☎️ **Clean contact fields**: phone numbers are converted to international form (`+493031800580`) when they are valid for the place's country; numbers that do not parse are kept as the source wrote them. Click-tracking parameters (`utm_*`, `gclid`, `fbclid`) are removed from websites.
- 🧾 **Honest run summary**: release used, candidates, duplicates dropped, how many rows have a website, phone or role e-mail.
- 💵 **$1 per 1,000 places**, down to $0.80 on Apify's Business plan and higher. No start fee. Locations that are not found, filtered-out places and duplicates are free.

### What data do you get?

#### Output example

One row per business (key fields; the `full` view has more):

```json
{
    "id": "eb8be1be-fb13-4309-84af-f2578e753841",
    "name": "Gragger Brot",
    "category": "bakery",
    "categoryPath": ["food_and_drink", "casual_eatery", "bakery"],
    "website": "http://www.gragger.de/",
    "phone": "+493081866477",
    "emails": ["marketing@gragger.de"],
    "contactEmails": ["marketing@gragger.de"],
    "contactPhones": ["+493081866477"],
    "contactSocials": [],
    "emailType": "role-only",
    "address": "Potsdamer Str. 107",
    "city": "Berlin",
    "postcode": "10785",
    "country": "DE",
    "latitude": 52.5,
    "longitude": 13.36,
    "confidence": 0.996,
    "sourceUpdated": "2026-09-14",
    "retrievedAt": "2026-10-21T08:00:00.000Z",
    "lastVerifiedAt": null,
    "release": "2026-09-23.1",
    "license": "CDLA-Permissive-2.0",
    "attribution": "© Overture Maps Foundation (places)"
}
```

The coordinates and timestamps are illustrative; real rows carry full precision and the run's actual timestamps. With enrichment, the row also has `enrichedEmails`, `enrichedPhones`, `enrichedSocials`, a non-null `lastVerifiedAt` after this Actor's contact reader successfully reads the website, and flat `linkedIns`, `twitters`, `instagrams`, `facebooks`, `youtubes`, `tiktoks` URL arrays where present. Company classification has no verifiable check timestamp, so `lastVerifiedAt` stays null.

**What the data is not**: Overture has **no ratings, reviews or opening hours**, and only about 1 in 5 places has an e-mail address. It is a business directory, not a review database. For contact details beyond the source data, switch on the optional enrichment below, which reads each business's own website.

### Input example

The form is prefilled with dental clinics in Lisbon, capped at 20 places (about $0.02, done in under a minute). A bigger input:

```json
{
    "locations": ["Lisbon, PT", "Porto, PT"],
    "categories": ["restaurant", "hotel"],
    "requireWebsite": true,
    "maxResults": 2000,
    "enrich": "contacts",
    "enrichRequire": "email"
}
```

### Next step: from places to verified email leads

Places Database gives you the businesses and their websites. Three TidyTools Actors turn that list into e-mail leads, each reading the previous run's dataset (copy the **dataset ID** from the run's *Storage* tab, or use `{{resource.defaultDatasetId}}` in an Apify integration):

| Step | Actor | What it adds | Price |
|---|---|---|---|
| 1 | **Places Database** (this Actor) | businesses, websites, phones | $1 per 1,000 places |
| 2 | [Website Email Extractor for Google Maps Leads & Domain Lists](https://apify.com/tidytools/website-contact-extractor) | e-mails, phones and social links read from each website | $2 per 1,000 websites with a contact found |
| 3 | [Email List Cleaner - Bulk Email Validator](https://apify.com/tidytools/bulk-email-validator) | syntax, domain/MX and disposable checks on every address | $0.50 per 1,000 e-mails |
| 4 | [Google Maps Lead Enrichment - Company Enrichment](https://apify.com/tidytools/company-website-enrichment) | industry, business model, description, tech stack | $6 per 1,000 companies classified |

Copy-paste inputs (paste into each Actor's JSON input; replace the IDs with your own runs' dataset IDs):

1. Places Database:
   ```json
   { "locations": ["Austin, US"], "categories": ["dentist"], "requireWebsite": true, "maxResults": 500 }
   ```
2. Website Email Extractor, reading the websites of step 1 and keeping each place's id, name, phone and city:
   ```json
   { "datasetId": "<dataset ID of step 1>", "datasetField": "website", "datasetKeepFields": ["id", "name", "phone", "city"] }
   ```
3. Email List Cleaner, checking every address found in step 2:
   ```json
   { "datasetId": "<dataset ID of step 2>", "datasetField": "emails" }
   ```
4. Company enrichment (optional), classifying the companies of step 1:
   ```json
   { "datasetId": "<dataset ID of step 1>", "datasetField": "website", "datasetKeepFields": ["id", "name"] }
   ```

For 500 dentists with a website, steps 1 and 2 cost at most $0.50 + $1.00; step 3 adds $0.0005 per address checked; step 4 adds at most $3.00. Want contacts in one run instead? Use **Add contacts or company details** below ($3 per 1,000 websites with a contact found).

### Three ways to buy the result

Pick what you need with **Add contacts or company details**. The log prints the cost of each option before the run starts.

| Option | What you get | Price |
|---|---|---|
| **Directory only** (default) | Name, category, address, coordinates, website, phone, role emails and socials from the open data | $1 per 1,000 places |
| **+ Contact enrichment** | Directory + emails, phones and social links read from each business's own website | + $3 per 1,000 websites **where a contact was found** (with *Email only*: where an email was found) |
| **+ Company classification** | Directory + industry, business model, description, contacts and tech stack, by [Company Website Enrichment](https://apify.com/tidytools/company-website-enrichment) | + $6 per 1,000 companies classified, billed by that Actor |

Worked example, 100 dental clinics with a website in Berlin (measured 2 Oct 2026): directory $0.10; with contact enrichment $0.10 + 88 websites x $0.003 = $0.36; 69 of the 100 had an email address a buyer would see (role addresses), 51 of them new compared with the source data.

How enrichment behaves:

- **Source values are never overwritten.** What a website adds goes into `enrichedEmails`, `enrichedPhones`, `enrichedSocials` and an `enrichment` object (status, pages read, whether the page loaded, where each email was found).
- **Export one contact list per business.** `contactEmails`, `contactPhones` and `contactSocials` deduplicate source and website values. The social platform arrays use the same names seen in many Maps exports; they contain URLs, not enriched profile statistics.
- **"Contact found" means the website showed one**, even when it is the same address the source data already had; you pay for the website read that found it (`enrichment.status: "found"`), not only for new addresses.
- **A website shared by several places** (chains, branches) is read and charged once; every place keeps its own `id`, so branches are never merged.
- **No website in the source** means the website is *unknown*, not that the business has none. Such places are not charged for enrichment.
- **A website that loads does not prove the business still operates.** `websiteReachable` only says the page opened.
- Only role addresses (info@, contact@...) are returned unless you switch on personal addresses, the same rule as the directory data.
- **The website reader identifies itself and respects robots.txt.** Its user agent is `TidyToolsContacts/1.0 (+https://apify.com/tidytools)` (`TidyToolsSmartFetch` from our servers), never a browser's. Pages a website's robots.txt disallows are not read; a website whose home page is disallowed gets `enrichment.status: "robots_disallowed"` and is not charged.
- Contact-enrichment spending is capped by *Max websites to read* and by your run's maximum charge. Unreachable websites and websites with nothing found are free.
- Company classification runs as separate Company Website Enrichment runs, billed to you by that Actor. They are limited by *Max websites to read* (each sub-run gets its own maximum charge of $0.006 per website it is given), but they are **not** counted in this run's maximum charge.
- Cheaper for big lists: run the directory first, then give its dataset to [Website Email Extractor](https://apify.com/tidytools/website-contact-extractor) ($2 per 1,000 websites with a contact), as in the [next step](#next-step-from-places-to-verified-email-leads) section.

### What to expect from the source data

Measured on 600 random places (Berlin, Austin, Lisbon; restaurants and dental clinics; 100 each; Overture 2026-09-23.1):

- **Website field present:** 87% of places (restaurants 69-88%, dental clinics 91-94%). The rest have an unknown website.

- **Duplicates removed:** 0-3.5% of candidates.

- **Email in the source data:** 17% of places (11-30% by city and category). Phone, website or social link: 97%.

- **Home page opened** for 80% of the listed websites.

- **After reading the websites:** the share of places with an email address rises from 17% to 53% when personal addresses are allowed, and to 33% with role addresses only.

- **Source date:** it depends on the city and the business type. In the sample above 87% of the records carry a `sourceUpdated` date in September 2026, but 500 lawyers and accountants in London (10 Oct 2026) were 45% updated within the last 12 months and 55% older, many from 2014-2017 (Microsoft source), while Nairobi, Taipei and Cairo samples were almost all from 2026. Restricting to the last 12 months in London kept 1,117 of 3,463 candidates and raised the share with an e-mail from 34% to 61% in the first 300 rows. It is the date of the source dataset's record, not a check that the business is open. About 1 in 9 listed websites did not resolve in DNS and about 1 in 10 returned an error or timed out; that points at stale entries but does not prove a closure.

These are samples, not guarantees: your city and category will differ.

### Use with AI agents (MCP)

Connect Apify's MCP server (https://mcp.apify.com?tools=tidytools/places-database) to Claude, Cursor or any MCP client, then ask e.g. "list 200 dental clinics with a website in Lisbon". Minimal input:

```json
{ "locations": ["Lisbon, PT"], "categories": ["dental_clinic"], "maxResults": 200 }
```

Problems come back as free rows with an `errorType` (`invalid_input`, `not_found`, `no_results`, `failed`) and a plain explanation; the run still ends normally. They are not charged.

### Pricing

**$1 per 1,000 places** (`place-returned` event), $0.90 on Silver, $0.80 on Gold and above. **No start fee.** You pay only for places that are returned. Optional contact enrichment adds **$3 per 1,000 websites with a contact found** (`place-enriched`; $2.70 on Silver, $2.40 on Gold and above); company classification is billed by Company Website Enrichment. A run's worst case is shown in the log before it starts and is capped by your *Max places* and your run's maximum charge; company classification sub-runs are billed separately and are not counted in that maximum.

### Limitations

- **No ratings, reviews, opening hours or photos.** Overture is a business directory; use a map scraper if you need those.
- **E-mail coverage is low in the source** (about 1 in 5 places). Contact enrichment raises it by reading each business's website, at an extra cost.
- **A snapshot, not a live check.** Some places have closed or moved since the source was updated; `confidence` and `sourceUpdated` help you judge.
- **Category names are Overture's.** Common words are translated (about 50 business types, in English and several other languages); anything else must be an Overture category name. A category that does not exist returns nothing (a free `no_results` row suggests the most common ones in your area), and a word the Actor cannot read at all ends the run with a free `invalid_input` row before anything is charged.
- **Cities without a country code are guesses.** `Springfield` becomes the best-known Springfield (Illinois); the run summary and log name the place used. Write `Springfield, US` or another country code to be sure. A US state after the comma (`Springfield, Illinois`) is read as the United States and is not used to pick the city: use a box to choose between cities of the same name.
- **The source is older in some places.** The share of records not updated for a year varies from almost none (Nairobi, Taipei) to more than half (London lawyers and accountants); use *Max source age* if freshness matters more than volume.
- **Major cities mean the urban area.** For about 290 big cities the search box covers the whole urban area, so nearby towns appear; use the `city` field or a smaller box to narrow it.
- **Chains have many rows.** Every branch is its own place with its own `id`; branches are listed after the distinct businesses but are not merged.
- **Whole countries are slow.** Add categories and a *Max places* limit; very large areas may need several runs.

### Responsible use

This Actor returns **business information**. Please use it responsibly:

- **Personal data.** Some businesses are one-person practices, and their phone number or address is then personal data. This Actor does not extract person names and returns only role e-mail addresses by default. If you switch on **Also return personal email addresses**, you are responsible for having a lawful basis (for example GDPR / ePrivacy in the EU, CAN-SPAM in the US, PECR in the UK) before you contact anyone.
- **Marketing rules.** Cold e-mail and calls are regulated in many countries. Check the rules for your target country, honour opt-outs, and keep a record of where each contact came from (the `release` and `attribution` fields help).
- **EU and UK.** If you process data of EU or UK residents you are the data controller of your own lead list.
- **No guarantees.** The data is a snapshot built from several sources, with an estimated confidence per place. Places can have closed or moved.

### Data source and attribution

Places come from the **Overture Maps Foundation** places dataset, read directly from Overture's public cloud storage. The places data is licensed under **CDLA-Permissive-2.0**; source datasets are listed per row in `sourceDataset`. If you republish the data, credit it as **"© Overture Maps Foundation"** and keep the license notice. Learn more at https://docs.overturemaps.org/. City boundaries are looked up with OpenStreetMap Nominatim (© OpenStreetMap contributors, ODbL) and used only to filter places; they are not part of the output.

### FAQ

**Does the Actor collect usage data?** The Actor sends one anonymous usage counter per run (input type, item count range, outcome) to improve the tool; no URLs, content or account data.

**Which release is used?** The newest Overture release by default (`latest`); the release name is in every row and in the run summary. You can pin one in the advanced settings. If the newest release cannot be read, the Actor falls back to the last release it was tested with.

**Why does my category return nothing?** Overture has its own category list. The run log then prints the most common categories in your area; use one of those, or a parent such as `food_and_drink`. Plain words such as `dentist`, `lawyer`, `accountant`, `car repair` and their German, French, Spanish, Portuguese, Italian, Dutch, Chinese and Japanese equivalents (`Zahnarzt`, `avocat`, `abogado`, `牙醫`, `歯科`) are translated for you.

**Why did my run end with "None of the categories could be used"?** Every category you entered was unreadable (for example only symbols, or a word in a language without a translation). The run ends with one free `invalid_input` row instead of returning every business in the area. Nothing is charged. Enter the category in English or as an Overture name.

**Why are there places from nearby towns?** For about 290 major cities (Austin, Berlin, Madrid...) the search covers the urban area, so suburbs such as Round Rock or Potsdam are included. Every row has `city`, `postcode` and coordinates, so you can filter them out. Smaller places use their official boundary.

**Which phone format do I get?** International E.164 (`+15122583008`) whenever the number is valid for the place's country; otherwise the number exactly as the source has it. `phones` holds every number of the place, `phone` the first one.

**Why did a location fail with "not a known country"?** The part after the comma must be a real ISO country code or an English country name (`Berlin, DE`, `Lisbon, Portugal`). `UK` is accepted and read as `GB`. A US state is read as the United States (`Austin, TX` is searched as `Austin, US`; the state itself is not used and the row note says which place was found). Be careful with state codes that are also country codes (`ME` is Montenegro, `AL` Albania): write `Portland, US`. Several places on one line, separated by `;`, are split into separate locations. Failed lines are free.

**Why did my box return nothing?** A box is written `west,south,east,north`, so **longitude first**. Latitude first (`59.4,24.7,59.5,24.8`) points at the wrong part of the world; the free `no_results` row then suggests the swapped box when that one has places.

**How big can a run be?** Cities up to a few hundred thousand places work in one run. Whole countries are possible but slow; always add categories and a *Max places* limit.

**Is this affiliated with any map provider?** No. It reads the open Overture dataset only.

### Your feedback

Found a wrong or missing category, or want another field? Open an issue on the Actor page.

# Actor input Schema

## `locations` (type: `array`):

One per line. A city with its 2-letter country code, e.g. `Berlin, DE` or `Austin, US` (the English name works; without a country code the biggest match is used), or a box as `west,south,east,north` in degrees, e.g. `13.30,52.48,13.45,52.56`. Cities are cut out along their real boundary. Use "Whole countries" for a country.

## `categories` (type: `array`):

JSON array of business types, e.g. {"categories":\["restaurant","dental_clinic"]}; enter one per line in the form. Overture category names and plain words such as dentist, lawyer or car repair work, including common translations. Spaces and plurals are accepted. A parent category such as food_and_drink includes its children. Empty selects every category; if none match, the run log suggests common categories for the area.

## `countries` (type: `array`):

2-letter ISO country codes, e.g. `DE`, `TW`. Slow for big countries: always add categories and keep Max places sensible.

## `maxResults` (type: `integer`):

Maximum number of places returned (and charged) in this run, across all locations. Best-scored places come first.

## `minConfidence` (type: `number`):

Overture's score (0 to 1) that the place really exists. 0.85 keeps well-supported places; lower it for more rows and more noise.

## `requireWebsite` (type: `boolean`):

Typical for lead lists you will enrich or email.

## `requirePhone` (type: `boolean`):

Keep only places that have a phone number in the source data.

## `requireEmail` (type: `boolean`):

Counts role addresses (info@, contact@...) unless you also allow personal addresses below. About 1 in 5 places has an email in the source data.

## `includePersonalEmails` (type: `boolean`):

Off (default): only role addresses such as info@, contact@, sales@ are returned. On: every email in the source data, including addresses that look like a named person (anna.meier@...). Personal addresses are personal data: you are responsible for having a lawful basis to use them (see Responsible use in the README).

## `maxResultsPerLocation` (type: `integer`):

Cap for each city or area, so one big city does not use the whole budget. Empty = no per-location cap.

## `maxSourceAgeMonths` (type: `integer`):

Keep only places whose source record (`sourceUpdated`) was updated within this many months, for example 12 for the last year. Empty = no limit. Older records are more likely to be closed or moved (in big cities about half of the records can be over a year old); the run summary shows how many returned places are older than 12 months. Records without a source date are kept.

## `includePhones` (type: `boolean`):

Business phone numbers from the source data. Turn off to return no phone numbers at all.

## `includeSocials` (type: `boolean`):

Facebook, Instagram and other profile links from the source data. Turn off to return none.

## `release` (type: `string`):

`latest` (default) or a release name such as `2026-09-23.1`. Overture publishes a new release about every month and removes old ones after a while.

## `maxConcurrency` (type: `integer`):

CPU threads for the query engine (1 to 4). More threads are faster on large areas and need more memory.

## `enrich` (type: `string`):

What to do with the websites in the source data. Default: nothing, you pay only the directory price. Places without a website field have an unknown website (not 'no website') and are never charged for enrichment. A website shared by several places (chains, branches) is read and charged once, and each place keeps its own id. Source values are never overwritten: what a website adds goes to `enrichedEmails`, `enrichedPhones`, `enrichedSocials` and `enrichment`.

## `enrichRequire` (type: `string`):

Only for 'Contact enrichment'. The charge applies when the website gave what you choose here. Phones and social links found are still returned when 'Email only' is selected.

## `enrichMaxWebsites` (type: `integer`):

Spending cap for enrichment: at most this many different websites are read in the run. Places over the cap are returned without enrichment (status skipped_cap).

## `enrichMaxPages` (type: `integer`):

Home page plus likely contact pages (contact, imprint/Impressum, about). The price per website is the same however many pages are read.

## `enrichConcurrency` (type: `integer`):

How many websites are read at the same time.

## `enrichSiteTimeoutSecs` (type: `integer`):

After this time no further pages of a website are started.

## `enrichHttpVia` (type: `string`):

Where the website pages are fetched from. Auto tries Apify's network first, then our servers, then a real browser.

## Actor input object example

```json
{
  "locations": [
    "Lisbon, PT"
  ],
  "categories": [
    "dental_clinic"
  ],
  "maxResults": 20,
  "minConfidence": 0.85,
  "requireWebsite": false,
  "requirePhone": false,
  "requireEmail": false,
  "includePersonalEmails": false,
  "includePhones": true,
  "includeSocials": true,
  "release": "latest",
  "maxConcurrency": 2,
  "enrich": "none",
  "enrichRequire": "any",
  "enrichMaxWebsites": 500,
  "enrichMaxPages": 4,
  "enrichConcurrency": 5,
  "enrichSiteTimeoutSecs": 60,
  "enrichHttpVia": "auto"
}
```

# Actor output Schema

## `places` (type: `string`):

No description

## `full` (type: `string`):

No description

## `summary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "locations": [
        "Lisbon, PT"
    ],
    "categories": [
        "dental_clinic"
    ],
    "maxResults": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("tidytools/places-database").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "locations": ["Lisbon, PT"],
    "categories": ["dental_clinic"],
    "maxResults": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("tidytools/places-database").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "locations": [
    "Lisbon, PT"
  ],
  "categories": [
    "dental_clinic"
  ],
  "maxResults": 20
}' |
apify call tidytools/places-database --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tidytools/places-database"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/jSovfkbjeiDdEMz7f/builds/r8G9iBiFpfO0hCRB0/openapi.json
