Understand business fields and contact data

Choose useful fields and interpret missing values before importing a dataset into your workflow.

  • 8 min read
  • Online + API

Every business returned by the Online scraper, the REST API, and the MCP server uses one versioned record schema. This guide explains what each field means, how contact details are found, and how to read an empty value correctly before the data reaches your spreadsheet or CRM. The Search API wraps these records in businesses, alongside total and params. MCP returns that response in structuredContent; it does not require a separate results request.

Structure

Anatomy of a record

Example Garden Hotel

Hotel · Café · Meeting venue

OPERATIONAL

4.7(128 reviews) · $$

  • 100 Example Lane, Austin, TX 78701, US
  • +1 512-555-0100, +1 512-555-0101
  • https://hotel.example
  • [email protected]
  • Monday: Open 24 hours · America/Chicago
place.placeId
sample-place-id
place.cid
1234567890123456789
place.location
30.2672, -97.7431
place.address.city
Austin
place.domain
hotel.example
place.claimed
true
place.enrichmentState
returned
place.observedAt
2026-09-22T00:00:00Z
The fictional sample business used throughout our documentation, rendered from its structured record.

In JSON, each record has a schemaVersion (currently 2026-09-22) and a place object with every field. CSV and Excel exports flatten the same data into named columns. Fields are always present in JSON — when a value is unknown it is null or an empty array, never omitted.

Record (abridged)
{
  "schemaVersion": "2026-09-22",
  "place": {
    "placeId": "sample-place-id",
    "cid": "1234567890123456789",
    "name": "Example Garden Hotel",
    "category": "Hotel",
    "address": {
      "formatted": "100 Example Lane, Austin, TX 78701, US",
      "street": "100 Example Lane",
      "city": "Austin",
      "region": "Texas",
      "postalCode": "78701",
      "countryCode": "us",
      "municipality": "Downtown"
    },
    "location": {
      "latitude": 30.2672,
      "longitude": -97.7431
    },
    "phone": "+1 512-555-0100",
    "website": "https://hotel.example",
    "rating": 4.7,
    "reviewCount": 128,
    "emails": [
      "[email protected]"
    ],
    "…": "…"
  }
}

Reference

Field groups

Identity

FieldMeaning
nameBusiness name as shown on Google Maps.
category · categoriesPrimary category and the full list of categories.
placeId · cid · dataId · kgmidGoogle identifiers. Use them to match and de-duplicate records (dataId appears as Fid in CSV).
businessStatusFor example OPERATIONAL or CLOSED_TEMPORARILY, when shown.
claimed · ownerWhether the listing is owner-verified, and the owner profile when public.

Location

FieldMeaning
address.formattedFull one-line address.
address.street · municipality · city · region · postalCode · countryCodeParsed components. Some may be null when Google Maps does not show them separately.
location.latitude · longitudePin coordinates, for mapping and distance calculations.
plusCode · timeZoneOpen Location Code and IANA time zone, when available.

Contact

FieldMeaning
phone · phonesPrimary number and every listed number.
website · domainWebsite on the listing and its hostname.
emails · socialProfilesDiscovered on the business website during enrichment (see below).
contacts[]Evidence for each discovered email or social link: value, source page URL, method, and time observed.

Reputation & media

FieldMeaning
rating · reviewCountAverage star rating (0–5) and total number of reviews on the listing.
reviews · reviewsStateUp to 10 sample reviews when returned, and whether they were returned, unavailable, or not requested.
photos · photosState · featuredImageUrlUp to 20 photo/video metadata records and the listing’s main image.
reviewUrl · mapsUrl · knowledgeUrlLinks back to the source listing.

Details & provenance

FieldMeaning
openingHoursObject keyed by weekday, each an array of time ranges such as "9 AM–5 PM".
description · priceRange · amenities · about · hotelClass · noteListing attributes; about groups options such as Accessibility or Amenities.
observedAt · languageWhen the listing was captured and in which language.
enrichmentState · contactsCheckedAt · fieldStatesHow complete the contact enrichment is, and per-field status (see Interpret missing values).

Contact data

Where emails and social profiles come from

Google Maps listings show a phone number and website, but not emails. When enrichment runs, G Maps Crawl visits the listed website — the homepage and up to a few likely contact pages — and extracts business email addresses and social profile links. Each finding is recorded in contacts[] with the exact page it came from.

Contact evidence
[
  {
    "kind": "email",
    "value": "[email protected]",
    "sourceUrl": "https://hotel.example/contact",
    "observedAt": "2026-09-22T00:01:00Z",
    "method": "website"
  },
  {
    "kind": "social",
    "value": "https://www.instagram.com/examplegardenhotel/",
    "sourceUrl": "https://hotel.example",
    "observedAt": "2026-09-22T00:01:00Z",
    "method": "website"
  }
]
ProductHow to get emails & social profiles
Online scraperIncluded on paid Online plans (Lite and above). Not available on Free.
REST API / MCPRequest extra: true on REST POST /api/v1/search or MCP search_google_maps. The default is false; contact availability depends on the source.

Data quality

Interpret missing values

An empty value means “not found in the public sources we checked”, not “this business has no phone or email”. Three state fields tell you why something is empty:

enrichmentState values
enrichmentStateMeaning
returnedThe website was checked and at least one email or social link was found.
not_foundThe website was checked; no contact details were published on the pages visited.
not_applicableThe listing has no website, so there was nothing to check.
failedThe website could not be read (timeout, blocked, or error). Retrying later may help.
pendingEnrichment was not run or has not finished for this record.

fieldStates gives the same kind of answer for individual fields — observed, not_found, unsupported, failed, or pending — for example { "emails": "not_found", "socialProfiles": "observed" }. reviewsState and photosState do the same for sample reviews and photos.

Measure coverage before you commit

coverage.js
// Pass the businesses array from a search response, or Online JSON records
const fields = ["phone", "website", "emails", "socialProfiles", "rating", "openingHours"];

function coverage(records) {
  return Object.fromEntries(
    fields.map((field) => {
      const present = records.filter(({ place }) => {
        const value = place[field];
        return Array.isArray(value) ? value.length > 0 : value !== null && value !== undefined;
      }).length;
      return [field, `${Math.round((present / records.length) * 100)}%`];
    }),
  );
}

// → { phone: "92%", website: "78%", emails: "41%", socialProfiles: "55%", rating: "97%", openingHours: "88%" }

Joining data

Match and de-duplicate records

Chains, franchises, and businesses with common names often share a name across many locations. Overlapping searches (for example neighboring neighborhoods) also return the same listing more than once. Match on identifiers in this order:

  1. placeId — CSV column Place Id
  2. cid — CSV column Cid
  3. dataId — CSV column Fid
  4. Only as a last resort: name plus formatted address
dedupe.js
// Prefer stable identifiers, never the business name alone
function identity({ place }) {
  return place.placeId ?? place.cid ?? place.dataId ?? `${place.name}|${place.address.formatted}`;
}

function dedupe(records) {
  const seen = new Map();
  for (const record of records) {
    const key = identity(record);
    const previous = seen.get(key);
    // Keep the most recently observed copy
    if (!previous || previous.place.observedAt < record.place.observedAt) seen.set(key, record);
  }
  return [...seen.values()];
}

CSV & Excel

Spreadsheet columns

CSV and Excel files use the same 36 columns, in this order. Lists such as Phones, Email, and Categories are joined with ; , booleans become Yes/No, and nested objects such as Opening Hours become Monday: 9 AM–5 PM; Tuesday: ….

CSV column to JSON field mapping
#ColumnJSON path (under place)
1Namename
2Descriptiondescription
3Fulladdressaddress.formatted
4Streetaddress.street
5Municipalityaddress.municipality
6Categoriescategories
7Aboutabout
8Plus CodeplusCode
9Time ZonetimeZone
10PricepriceRange
11Notenote
12Amenitiesamenities
13Hotel ClasshotelClass
14Phonephone
15Phonesphones
16Claimedclaimed
17Ownerowner.name
18Owner Idowner.id
19Owner Linkowner.profileUrl
20Emailemails
21Social MediassocialProfiles
22Review CountreviewCount
23Average Ratingrating
24Review URLreviewUrl
25Google Maps URLmapsUrl
26Google Knowledge URLknowledgeUrl
27Latitudelocation.latitude
28Longitudelocation.longitude
29Websitewebsite
30Domaindomain
31Opening HoursopeningHours
32Featured ImagefeaturedImageUrl
33Cidcid
34FiddataId
35Place IdplaceId
36Kgmidkgmid

Recap

Before you import

  • Decide which fields your workflow actually needs, and check their coverage first.
  • Treat empty contact fields as unknown; read enrichmentState before drawing conclusions.
  • De-duplicate on Place Id / Cid, not on name.
  • Keep observedAt and source URLs so you can tell how fresh each record is.
  • Remember that rating and review count describe the listing; they are not individual review records.
  • Review the public data notice and the rules that apply to how you use contact data.

Keep going

Take the next step

See the fields on your own search.

Run a free preview on the homepage, then open the full dataset in your workspace.