# Bulk Address Verification API - US, Canada and Worldwide (`nabeelbaghoor/bulk-address-verification-api`) Actor

Verify, correct and standardize postal addresses in the US, Canada and worldwide. Freeform or structured input, batches of up to 2000 addresses per call, ZIP+4, county, delivery point validation and geocodes, plus address suggestions, address parsing and postal code lookups. Bring your own API key.

- **URL**: https://apify.com/nabeelbaghoor/bulk-address-verification-api.md
- **Developed by:** [Nabeel Hassan](https://apify.com/nabeelbaghoor) (community)
- **Categories:** Business, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$8.00 / 1,000 address result returneds

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Bulk Address Verification API - US, Canada and Worldwide

Clean a mailing list before you spend money on it: verify, correct and standardize postal addresses in the US, Canada and worldwide, in batches of up to 2000 addresses per call.

### What it does

- **Two coverage areas, one output shape.** The US and Canada service returns USPS and Canada Post detail. The worldwide service covers the rest of the world with a formatted address and a match score. Both write the same core columns, so results from the two are comparable side by side.
- **Corrects rather than only judging.** An address comes back standardized, with the status saying whether it was already right, was corrected, or failed. A typo in a street name, a missing direction or a wrong city are fixed rather than reported.
- **Returns the detail that decides postage.** ZIP+4, county and FIPS code, carrier route, delivery point validation, eLOT sequence, residential and vacancy flags, time zone and area code.
- **Geocodes as it verifies.** Latitude, longitude and an accuracy level, at rooftop level where the data supports it, without a second lookup.
- **Takes freeform or structured input.** A single line pasted from a form, or the separate columns you already hold. Common spreadsheet column names are accepted and rewritten to the provider's own.
- **Batches up to the provider's ceiling.** 2000 addresses per call, at a batch size you control, because a batch larger than the lookups left on your account fails as a whole.
- **Suggests candidates when an address fails.** Suggestion mode answers "what might this have meant", including unit number ranges for a building.
- **Parses one line into components.** House number, road, unit, floor, PO box, postcode, suburb, city district, city, county, state and country.
- **Goes both ways on postal codes.** A ZIP or postal code returns the cities and counties it covers with the mailable flag, and a US city and state returns every ZIP code inside it.
- **Keeps the misses.** An address nobody could verify still produces a row saying so, and rows this actor refused before sending are never charged for.

### Input

#### Verify a list of addresses

```json
{
  "mode": "verify",
  "addresses": [
    "111 Deerwood Rd Ste 200, San Ramon CA 94583 US",
    "20 Bay St, Toronto ON M5J 2N8 CA"
  ],
  "includeDetails": true,
  "maxResults": 1000
}
```

#### Verify addresses you hold as columns

```json
{
  "mode": "verify",
  "structuredAddresses": [
    { "line1": "90 Canal St", "city": "Boston", "provinceOrState": "MA", "postalOrZip": "02114", "country": "US", "id": "row-1" },
    { "line1": "20-20 Bay St", "city": "Toronto", "provinceOrState": "ON", "postalOrZip": "M9V 4V1", "country": "CA", "id": "row-2" }
  ],
  "batchSize": 500
}
```

#### Verify addresses outside North America

```json
{
  "mode": "verifyInternational",
  "addresses": ["Sageweg 27, 79395 Neuenburg, DE"],
  "geoData": true
}
```

### Example output

One row per address.

```json
{
  "input": "111 Deerwood Rd Ste 200, San Ramon CA 94583 US",
  "coverage": "us_ca",
  "status": "corrected",
  "verified": true,
  "corrected": true,
  "line1": "111 DEERWOOD RD STE 200",
  "city": "SAN RAMON",
  "provinceOrState": "CA",
  "provinceOrStateName": "CALIFORNIA",
  "postalOrZip": "94583",
  "zipPlus4": "4445",
  "country": "us",
  "countryName": "UNITED STATES",
  "streetNumber": "111",
  "streetName": "DEERWOOD",
  "streetType": "RD",
  "suiteKey": "STE",
  "suiteID": "200",
  "county": "CONTRA COSTA",
  "countyFIPS": "13",
  "residential": false,
  "vacant": false,
  "carrierRoute": "C027",
  "dpvConfirmation": "Y",
  "latitude": 37.7659,
  "longitude": -121.9585,
  "geocodeAccuracy": "rooftop"
}
```

### Frequently asked questions

#### What is the difference between the US and Canada mode and the worldwide mode?

They are two different services at the provider, with different data behind them. The US and Canada service is built on USPS and Canada Post data and returns postal detail: ZIP+4, carrier route, delivery point validation, county and a rooftop geocode. The worldwide service covers more than 240 countries and returns a formatted address, a verification status, a match level and a match score instead. Pick the one that matches where your list is, and run the list twice if it spans both.

#### Does it correct addresses or only check them?

It corrects them. A verified address comes back in the postal authority's own standardized form, with the status saying whether the input was already correct or had to be changed. The status is `verified` when the input was right, `corrected` when the provider fixed something, and `failed` when no real address matches.

#### Can I verify addresses in bulk?

Yes. Up to 2000 addresses go in one call, and the batch size is yours to set. Bear in mind that a batch larger than the lookups remaining on your account fails as a whole rather than in part, so a smaller batch size is safer when an allowance is nearly used up.

#### What is ZIP+4 and why does it matter?

ZIP+4 is the four digit extension the USPS adds to a five digit ZIP code to identify a specific block, building or delivery point. Mail sorted with it qualifies for lower postage rates and gets delivered more reliably, which is usually the reason a mailing list gets verified in the first place.

#### Can I tell residential addresses from business addresses?

Yes, on US addresses. The detail block carries a residential flag, a vacancy flag and the delivery point validation indicator, which together tell you whether an address is a home, a business, and whether anybody is currently receiving mail there.

#### What happens to an address that cannot be verified?

It still produces a row, with `verified` set to false and the provider's own error notes saying what was wrong, for example a missing suite identifier or a typo in the street name. Suggestion mode then takes the same address and returns the candidates it might have meant, which is the usual next step for a list that is mostly good with a bad tail.

#### Do I need my own API key?

Yes. This actor is bring your own key: it calls the address verification API using your own account key, so you keep your own lookup allowance, your own rate limits and your own data agreement. Create the key in the provider's dashboard under Developers, and use a live key rather than a test key, because a test key only answers test data.

#### How many free lookups do I get?

That is set by your own account rather than by this actor. The run reports how many of the free lookups on your key have been used and how many are left before it starts, so a run that is about to exhaust an allowance says so rather than failing halfway through.

#### How much does a run cost?

Charging is per row, and only rows the provider answered are charged. A confirmed undeliverable address counts as an answer, because the provider spent a lookup to establish it. Rows this actor refused before sending, and batches the provider would not process, are free. Set `maxResults` to cap the rows a run can produce.

#### What are the rate limits?

The provider documents five requests a second with a throughput of about 100 addresses a second. This actor paces itself at 120 requests a minute by default and is capped at 240, which leaves headroom on an account that is also serving your own application. Because batching sends up to 2000 addresses in one request, the request rate is rarely the limit that matters.

### Keyword map

address verification API, address validation API, bulk address verification, USPS address validation, CASS address standardization, ZIP+4 lookup, Canada Post address verification, international address verification, global address validation, address autocomplete API, address parsing API, address suggestion API, ZIP code lookup by city, city and state from ZIP code, delivery point validation, DPV confirmation, residential or business address, address geocoding API, mailing list cleaning, direct mail address hygiene

# Actor input Schema

## `mode` (type: `string`):

Verification cleans and standardizes addresses, and comes in two coverage areas because the provider runs two services: one for the US and Canada with USPS and Canada Post detail, one for the rest of the world. The other modes answer smaller questions: suggestions offer candidates for an address that did not verify, parsing breaks a line into components, and the two postal code modes go between a code and the places it covers.

## `apiKey` (type: `string`):

Your own account's API key for this provider, created in its dashboard under Developers. Bring your own key: nothing is shared between runs and the key is never written to the dataset. A test key only answers test data, so use a live key for real addresses.

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

One entry per line. In the verification and suggestion modes a line is a whole address written on one line, and adding the two letter country code at the end improves the match. In parse mode it is the address to break apart. In city and state lookup mode it is a ZIP or postal code. In ZIP code lookup mode it is a US city and state, for example New York, NY.

## `structuredAddresses` (type: `array`):

Addresses you already hold as separate columns, one object per address, used by the two verification modes and by suggestions. Fields are the provider's own: line1, line2, city, provinceOrState, postalOrZip, country, firmName, recipient and id. Common spreadsheet names such as street, state, zip, postcode, company and name are accepted and rewritten. Only line1 is required.

## `defaultCountry` (type: `string`):

Country applied to a structured address that does not carry one, as a two letter ISO code. Leave it empty to send those addresses without a country and let the provider infer it.

## `includeDetails` (type: `boolean`):

Ask for the full detail block on each verified address: street number, name, type and direction, suite, county and FIPS code, carrier route, delivery point validation, residential and vacancy flags, time zone and area code. Turning it off returns only the standardized address.

## `geoData` (type: `boolean`):

Ask the worldwide service for latitude, longitude and a geocode accuracy level on each address. Only applies to worldwide verification, because the US and Canada service returns its geocode without being asked.

## `skipUnverified` (type: `boolean`):

Leave addresses that did not verify out of the dataset. They are still counted and still billed by the provider, because the lookup happened either way, so this is about the shape of your output rather than the cost of the run.

## `batchSize` (type: `integer`):

How many addresses go into one batch call, up to the provider's ceiling of 2000. Larger batches are faster and cheaper in requests, but a batch bigger than the lookups left on your account fails as a whole, so lower this when an allowance is nearly spent.

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

Stop after this many rows. Some modes return several rows for one entry, for example a suggestion list or every ZIP code in a city, so this is a cap on output rather than on input.

## `requestsPerMinute` (type: `integer`):

How fast this actor calls the provider. The documented limit is five requests a second, so this is capped at 240 a minute, which leaves headroom on an account that is also serving your own application.

## Actor input object example

```json
{
  "mode": "verify",
  "addresses": [
    "111 Deerwood Rd Ste 200, San Ramon CA 94583 US"
  ],
  "structuredAddresses": [
    {
      "line1": "90 Canal St",
      "city": "Boston",
      "provinceOrState": "MA",
      "postalOrZip": "02114",
      "country": "US",
      "id": "row-1"
    }
  ],
  "defaultCountry": "US",
  "includeDetails": true,
  "geoData": false,
  "skipUnverified": false,
  "batchSize": 500,
  "maxResults": 100,
  "requestsPerMinute": 120
}
```

# Actor output Schema

## `addresses` (type: `string`):

One row per address, suggestion, parsed line or postal code, alongside the entry it came from.

# 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": [
        "111 Deerwood Rd Ste 200, San Ramon CA 94583 US"
    ],
    "structuredAddresses": [
        {
            "line1": "90 Canal St",
            "city": "Boston",
            "provinceOrState": "MA",
            "postalOrZip": "02114",
            "country": "US",
            "id": "row-1"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("nabeelbaghoor/bulk-address-verification-api").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": ["111 Deerwood Rd Ste 200, San Ramon CA 94583 US"],
    "structuredAddresses": [{
            "line1": "90 Canal St",
            "city": "Boston",
            "provinceOrState": "MA",
            "postalOrZip": "02114",
            "country": "US",
            "id": "row-1",
        }],
}

# Run the Actor and wait for it to finish
run = client.actor("nabeelbaghoor/bulk-address-verification-api").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": [
    "111 Deerwood Rd Ste 200, San Ramon CA 94583 US"
  ],
  "structuredAddresses": [
    {
      "line1": "90 Canal St",
      "city": "Boston",
      "provinceOrState": "MA",
      "postalOrZip": "02114",
      "country": "US",
      "id": "row-1"
    }
  ]
}' |
apify call nabeelbaghoor/bulk-address-verification-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nabeelbaghoor/bulk-address-verification-api"
        }
    }
}

```

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/JhhRtITfhTWRozTYU/builds/cu6zztYqZMJRC43i0/openapi.json
