# Google Geocoding Scraper - Most Comprehensive (`kaix/google-geocoding-scraper`) Actor

🔥 ~$0.1/1K addresses 🔥 Forward and reverse geocode with Google: addresses to coordinates, coordinates to addresses. Structured address components, place IDs, viewport, plus codes. No Google API key required.

- **URL**: https://apify.com/kaix/google-geocoding-scraper.md
- **Developed by:** [Kai](https://apify.com/kaix) (community)
- **Categories:** Developer tools, Integrations, AI
- **Features:** Limited permissions
- **Stats:** 77 total users, 27 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.10 / 1,000 addresses

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Google Geocoding Scraper

Convert addresses to coordinates, or coordinates to structured addresses. Each query produces one Dataset record with its status, matches, normalised address parts, Place IDs, map bounds, and available location metadata.

### Choose the geocoding direction

| Goal | Query field | Settings that apply |
|---|---|---|
| Convert an address or place description to coordinates | `addresses` | `language`, `region`, `components`, and `bounds` |
| Convert coordinates to nearby addresses and geographic areas | `latlngs` | `language`, `resultType`, and `locationType` |

You can submit both query types in one run. Each input occurrence produces its
own Dataset record, including repeated queries and queries with no match.

### Quick start

#### Addresses to coordinates

```json
{
  "addresses": [
    "Eiffel Tower, Paris, France",
    "Sydney Opera House, Australia"
  ]
}
```

#### Coordinates to addresses

```json
{
  "latlngs": [
    "40.748817,-73.985428",
    "48.8584,2.2945"
  ]
}
```

#### Run both query types

```json
{
  "addresses": ["Times Square, New York"],
  "latlngs": ["34.0522,-118.2437"],
  "maxConcurrency": 20
}
```

#### Localise and bias an ambiguous place

Use `language` for the preferred result language and `region` to influence the
ranking of an ambiguous forward query:

```json
{
  "addresses": ["Toledo"],
  "language": "es",
  "region": "es"
}
```

#### Restrict a forward query by country and viewport

Use `components` to restrict eligible results. Use `bounds` to influence their
ranking inside a viewport.

```json
{
  "addresses": ["Springfield"],
  "components": "country:US",
  "bounds": "39.70,-89.80|40.10,-89.40"
}
```

#### Filter reverse results

Use `resultType` and `locationType` when one coordinate returns more geographic
levels than you need:

```json
{
  "latlngs": ["37.4224764,-122.0842499"],
  "resultType": "street_address",
  "locationType": "ROOFTOP"
}
```

### Input

At least one item in `addresses` or `latlngs` must contain one or more characters. You can provide both arrays in one run. For compatibility, the Actor does not trim submitted strings or optional text values, so it accepts whitespace-only values. The Actor keeps repeated queries, so each input occurrence has its own output record.

The complete example below combines all forward, reverse, shared, and
connection fields. Forward-only settings do not affect coordinate queries, and
reverse-only settings do not affect address queries.

<details>
<summary>Complete input example</summary>

#### Forward and reverse settings

Forward-only settings apply to `addresses`. Reverse-only settings apply to `latlngs`.

```json
{
  "addresses": [
    "123 Main Stret, Brooklin, NY",
    "11968",
    "fjqpwoeiruzxcvmnbqwerty xyz 99999 nowhere"
  ],
  "latlngs": [
    "37.4224764,-122.0842499",
    "40.6782,-73.9442",
    "59.3293,18.0686",
    "notacoordinate"
  ],
  "language": "en",
  "region": "us",
  "components": "country:US",
  "bounds": "40.4774,-74.2591|40.9176,-73.7004",
  "resultType": "street_address|locality|postal_code|neighborhood|sublocality",
  "locationType": "ROOFTOP|RANGE_INTERPOLATED|GEOMETRIC_CENTER|APPROXIMATE",
  "maxConcurrency": 7,
  "proxyConfiguration": { "useApifyProxy": true }
}
```

</details>

#### Input reference

| Field | Type | Default | Applies to | Description |
| --- | --- | --- | --- | --- |
| `addresses` | string\[] | none | Forward | Addresses or place descriptions to convert into coordinates. |
| `latlngs` | string\[] | none | Reverse | Coordinates written as `latitude,longitude`. |
| `language` | string | none | Both | Preferred result language, such as `en`, `ja`, `de`, or `fr`. |
| `region` | string | none | Forward | Country-code region bias, such as `us`, `uk`, or `de`. This changes ranking but is not a strict country filter. |
| `components` | string | none | Forward | Component filter such as `country:US` or `country:US\|postal_code:94043`. |
| `bounds` | string | none | Forward | Viewport bias written as `southwestLat,southwestLng\|northeastLat,northeastLng`. |
| `resultType` | string | none | Reverse | Pipe-separated result types such as `street_address\|locality`. |
| `locationType` | string | none | Reverse | Pipe-separated precision filters such as `ROOFTOP\|APPROXIMATE`. |
| `maxConcurrency` | integer | `10` | Both | Number of queries processed in parallel. Allowed range: 1 to 50. |
| `proxyConfiguration` | object | `{"useApifyProxy":true}` | Both | Optional connection settings for the run. |

Forward-only settings are ignored for coordinate queries. Reverse-only settings are ignored for address queries. Shared settings apply to every compatible query in the run.

### Output

The default Dataset contains one record for each submitted query. With concurrent work, Dataset order can differ from input order. Match records by `query` and `mode`.

| Field | Type | Description |
| --- | --- | --- |
| `query` | string | The submitted address or coordinate. |
| `mode` | string | `forward` or `reverse`. |
| `status` | string | `OK`, `ZERO_RESULTS`, `INVALID_REQUEST`, or `ERROR`. |
| `errorMessage` | string | Safe text for `INVALID_REQUEST` or `ERROR`. This field is omitted for other statuses. |
| `results` | array | Matched locations. This is empty for every non-`OK` status. |

Each result item can contain the fields in this table.

| Field | Type | Description |
| --- | --- | --- |
| `address` | string | Formatted address. |
| `placeId` | string | Google place identifier. |
| `lat`, `lng` | number | Result coordinates. |
| `locationType` | string | `ROOFTOP`, `RANGE_INTERPOLATED`, `GEOMETRIC_CENTER`, or `APPROXIMATE`. |
| `types` | string\[] | Result categories. The array can be empty. |
| `components` | object | Normalised address parts and the full `raw` component array. |
| `viewport` | object | Recommended map viewport with `ne` and `sw` corners. |
| `bounds` | object | Precise `ne` and `sw` bounds when available. |
| `partialMatch` | boolean | True when the result is an approximate or partial match. |
| `plusCode` | object | `globalCode` and `compoundCode` when available. |
| `postcodeLocalities` | string\[] | Localities represented by a postal code when available. |

`components` can contain `streetNumber`, `street`, `city`, `state`, `stateCode`, `country`, `countryCode`, `postalCode`, `neighborhood`, `sublocality`, and `administrativeAreaLevel2`. Each `components.raw[]` item contains `longName`, `shortName`, and `types`.

Some records contain many matches or address components. The examples below
shorten repeated arrays.

#### Forward result

This retained Dataset item is unchanged and matches the repository fixture for
`Eiffel Tower, Paris, France`.

<details>
<summary>Open the forward-geocoding JSON</summary>

```json
{
  "query": "Eiffel Tower, Paris, France",
  "mode": "forward",
  "status": "OK",
  "results": [
    {
      "address": "Av. Gustave Eiffel, 75007 Paris, France",
      "placeId": "ChIJLU7jZClu5kcR4PcOOO6p3I0",
      "lat": 48.85837009999999,
      "lng": 2.2944813,
      "locationType": "GEOMETRIC_CENTER",
      "types": [
        "establishment",
        "point_of_interest",
        "tourist_attraction"
      ],
      "components": {
        "street": "Avenue Gustave Eiffel",
        "city": "Paris",
        "state": "Île-de-France",
        "stateCode": "IDF",
        "country": "France",
        "countryCode": "FR",
        "postalCode": "75007",
        "administrativeAreaLevel2": "Paris",
        "raw": [
          {
            "longName": "Avenue Gustave Eiffel",
            "shortName": "Av. Gustave Eiffel",
            "types": ["route"]
          },
          {
            "longName": "Paris",
            "shortName": "Paris",
            "types": ["locality", "political"]
          },
          {
            "longName": "Paris",
            "shortName": "Paris",
            "types": ["administrative_area_level_2", "political"]
          },
          {
            "longName": "Île-de-France",
            "shortName": "IDF",
            "types": ["administrative_area_level_1", "political"]
          },
          {
            "longName": "France",
            "shortName": "FR",
            "types": ["country", "political"]
          },
          {
            "longName": "75007",
            "shortName": "75007",
            "types": ["postal_code"]
          }
        ]
      },
      "viewport": {
        "ne": {
          "lat": 48.8593817802915,
          "lng": 2.296314600000001
        },
        "sw": {
          "lat": 48.8566838197085,
          "lng": 2.2934008
        }
      },
      "partialMatch": false,
      "plusCode": {
        "globalCode": "8FW4V75V+8Q",
        "compoundCode": "V75V+8Q Paris, France"
      }
    }
  ]
}
```

</details>

#### Reverse result

This Brooklyn record keeps two matches to show the normalised components, `plusCode`, and `bounds`.

<details>
<summary>Open the reverse-geocoding JSON</summary>

```json
{
  "query": "40.6782,-73.9442",
  "mode": "reverse",
  "status": "OK",
  "results": [
    {
      "address": "1385-1387 Atlantic Ave, Brooklyn, NY 11216, USA",
      "placeId": "ChIJP6JvsIVbwokRVV-dxQ7GXRY",
      "lat": 40.6785037,
      "lng": -73.94391929999999,
      "locationType": "ROOFTOP",
      "types": [
        "street_address"
      ],
      "components": {
        "streetNumber": "1385-1387",
        "street": "Atlantic Avenue",
        "city": "Brooklyn",
        "state": "New York",
        "stateCode": "NY",
        "country": "United States",
        "countryCode": "US",
        "postalCode": "11216",
        "neighborhood": "Bedford-Stuyvesant",
        "sublocality": "Brooklyn",
        "administrativeAreaLevel2": "Kings County",
        "raw": [
          {
            "longName": "1385-1387",
            "shortName": "1385-1387",
            "types": [
              "street_number"
            ]
          }
        ]
      },
      "viewport": {
        "ne": {
          "lat": 40.6798255302915,
          "lng": -73.9425727197085
        },
        "sw": {
          "lat": 40.6771275697085,
          "lng": -73.9452706802915
        }
      },
      "partialMatch": false,
      "plusCode": {
        "globalCode": "87G8M3H4+CC",
        "compoundCode": "M3H4+CC Brooklyn, NY, USA"
      }
    },
    {
      "address": "1387 Brooklyn Ave, Brooklyn, NY 11216, USA",
      "placeId": "ChIJFzA3sIVbwokRAtwPnwGMv9k",
      "lat": 40.6783765,
      "lng": -73.9439933,
      "locationType": "ROOFTOP",
      "types": [
        "premise",
        "street_address"
      ],
      "components": {
        "streetNumber": "1387",
        "street": "Brooklyn Avenue",
        "city": "Brooklyn",
        "state": "New York",
        "stateCode": "NY",
        "country": "United States",
        "countryCode": "US",
        "postalCode": "11216",
        "neighborhood": "Bedford-Stuyvesant",
        "sublocality": "Brooklyn",
        "administrativeAreaLevel2": "Kings County",
        "raw": [
          {
            "longName": "1387",
            "shortName": "1387",
            "types": [
              "street_number"
            ]
          }
        ]
      },
      "viewport": {
        "ne": {
          "lat": 40.67972543029149,
          "lng": -73.94270711970849
        },
        "sw": {
          "lat": 40.6770274697085,
          "lng": -73.94540508029151
        }
      },
      "bounds": {
        "ne": {
          "lat": 40.678407,
          "lng": -73.94397359999999
        },
        "sw": {
          "lat": 40.6783459,
          "lng": -73.94401289999999
        }
      },
      "partialMatch": false
    }
  ]
}
```

</details>

<details>
<summary>Other result shapes</summary>

#### Postal-code localities

This example keeps the first match and all locality names for postal code `11968`.

```json
{
  "query": "11968",
  "mode": "forward",
  "status": "OK",
  "results": [
    {
      "address": "Southampton, NY 11968, USA",
      "placeId": "ChIJTUAcY3WT6IkRkQgjMpcRi-s",
      "lat": 40.9045168,
      "lng": -72.4139787,
      "locationType": "APPROXIMATE",
      "types": [
        "postal_code"
      ],
      "components": {
        "city": "Southampton",
        "state": "New York",
        "stateCode": "NY",
        "country": "United States",
        "countryCode": "US",
        "postalCode": "11968",
        "administrativeAreaLevel2": "Suffolk County",
        "raw": [
          {
            "longName": "11968",
            "shortName": "11968",
            "types": [
              "postal_code"
            ]
          }
        ]
      },
      "viewport": {
        "ne": {
          "lat": 40.9768871,
          "lng": -72.3232079
        },
        "sw": {
          "lat": 40.833188,
          "lng": -72.48820189999999
        }
      },
      "bounds": {
        "ne": {
          "lat": 40.9768871,
          "lng": -72.3232079
        },
        "sw": {
          "lat": 40.833188,
          "lng": -72.48820189999999
        }
      },
      "partialMatch": false,
      "postcodeLocalities": [
        "Art Village",
        "North Sea",
        "Shinnecock Hills",
        "Southampton",
        "Tuckahoe",
        "Water Mill"
      ]
    }
  ]
}
```

#### Partial match

The `components` filter in the earlier input changed the otherwise unmatched
text into this country-level partial match.

```json
{
  "query": "fjqpwoeiruzxcvmnbqwerty xyz 99999 nowhere",
  "mode": "forward",
  "status": "OK",
  "results": [
    {
      "address": "United States",
      "placeId": "ChIJCzYy5IS16lQRQrfeQ5K5Oxw",
      "lat": 38.7945952,
      "lng": -106.5348379,
      "locationType": "APPROXIMATE",
      "types": [
        "country",
        "political"
      ],
      "components": {
        "country": "United States",
        "countryCode": "US",
        "raw": [
          {
            "longName": "United States",
            "shortName": "US",
            "types": [
              "country",
              "political"
            ]
          }
        ]
      },
      "viewport": {
        "ne": {
          "lat": 72.7087158,
          "lng": -66.3193754
        },
        "sw": {
          "lat": 15.7760139,
          "lng": -173.2992296
        }
      },
      "bounds": {
        "ne": {
          "lat": 74.071038,
          "lng": -66.885417
        },
        "sw": {
          "lat": 18.7763,
          "lng": 166.9999999
        }
      },
      "partialMatch": true
    }
  ]
}
```

#### Queries without a match

These examples show each non-`OK` status.

```json
{
  "query": "notacoordinate",
  "mode": "reverse",
  "status": "INVALID_REQUEST",
  "errorMessage": "The query is invalid.",
  "results": []
}
```

The next record came from a separate run with the same text and no
`components` filter. That run returned no match.

```json
{
  "query": "fjqpwoeiruzxcvmnbqwerty xyz 99999 nowhere",
  "mode": "forward",
  "status": "ZERO_RESULTS",
  "results": []
}
```

```json
{
  "query": "Eiffel Tower, Paris, France",
  "mode": "forward",
  "status": "ERROR",
  "errorMessage": "The query could not be completed.",
  "results": []
}
```

</details>

### Status values

- `OK`: The query has at least one match.
- `ZERO_RESULTS`: The query is valid, but no location matched.
- `INVALID_REQUEST`: The coordinate or filter combination was not accepted.
- `ERROR`: This query could not be completed. Other queries in the batch continue.

If every query ends in `ERROR`, the records are still saved and the run completes successfully. Check `status` before you use a result.

#### Several reverse matches

One coordinate can match several geographic levels, such as a street address, neighbourhood, city, region, and country. Use `resultType` or `locationType` when you need a narrower result set.

#### An unexpected forward match

`region` and `bounds` change result ranking. They do not make a strict area filter. Use `components` when you need to restrict eligible forward results.

Every matched result includes its `placeId`, address, and coordinates.

# Actor input Schema

## `addresses` (type: `array`):

Addresses or place descriptions to geocode into coordinates.

## `latlngs` (type: `array`):

Coordinates as 'lat,lng' strings to reverse geocode into addresses.

## `language` (type: `string`):

Preferred result language, such as en, ja, de, or fr.

## `region` (type: `string`):

Country-code region bias for forward geocoding, such as us, uk, or de.

## `components` (type: `string`):

Component filter, e.g. 'country:US|postal_code:94043'.

## `bounds` (type: `string`):

Viewport bias as 'swLat,swLng|neLat,neLng'.

## `resultType` (type: `string`):

Filter reverse results by type, e.g. 'street_address|locality'.

## `locationType` (type: `string`):

Filter reverse results by location type, e.g. 'ROOFTOP|APPROXIMATE'.

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

Maximum number of queries processed in parallel.

## `proxyConfiguration` (type: `object`):

Optional connection routing settings.

## Actor input object example

```json
{
  "addresses": [
    "1600 Amphitheatre Parkway, Mountain View, CA"
  ],
  "latlngs": [
    "37.4224764,-122.0842499"
  ],
  "maxConcurrency": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (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 = {
    "addresses": [
        "1600 Amphitheatre Parkway, Mountain View, CA"
    ],
    "latlngs": [
        "37.4224764,-122.0842499"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("kaix/google-geocoding-scraper").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 = {
    "addresses": ["1600 Amphitheatre Parkway, Mountain View, CA"],
    "latlngs": ["37.4224764,-122.0842499"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("kaix/google-geocoding-scraper").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 '{
  "addresses": [
    "1600 Amphitheatre Parkway, Mountain View, CA"
  ],
  "latlngs": [
    "37.4224764,-122.0842499"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call kaix/google-geocoding-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,kaix/google-geocoding-scraper"
        }
    }
}
```

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/D1J8wC8nodVxcmWTi/builds/A5cZSpNOB6zeuZnJz/openapi.json
