# Email Append API - Demographics, Phones and Validation (`nabeelbaghoor/email-append-demographics-api`) Actor

Append an email address to a name and postal address, pull the age, income, household and interests behind an address, verify deliverability with a reason code and typo correction, find a person's other addresses, and check phone line type, carrier and connection status. Pay per result.

- **URL**: https://apify.com/nabeelbaghoor/email-append-demographics-api.md
- **Developed by:** [Nabeel Hassan](https://apify.com/nabeelbaghoor) (community)
- **Categories:** Business, Developer tools, Lead generation
- **Stats:** 2 total users, 1 monthly users, 71.4% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$15.00 / 1,000 results

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

## Email Append API - Demographics, Phones and Validation

Turn a name and a postal address into an email address, turn an email address into the household behind it, and check that any address or phone number you hold is still worth using. One flat row per address, person or number.

### What this actor does

- **Appends an email to a name and a postal address.** Give it a list of names paired line by line with postal addresses and it returns the address matched to that person, with a match type saying whether the match was to the individual or only to the household. Both the four part and the three part spelling of an address are understood, so a pasted list still works.
- **Returns the household behind an address.** Demographics gives you age, gender, postcode, household income, net worth, home value, home owner status, length of residence, marital status, presence of children, education, occupation, life stage, financial segment, recency and spend history, and the interests the provider holds. Interests arrive as dozens of booleans and are collapsed to a list of the ones that matched, so the row stays readable.
- **Validates deliverability and fixes typos.** Validation returns the verdict, the numeric reason code under it, the domain category, the role account flag and a zero to ten engagement quality score. When an address failed only because of a spelling mistake, the corrected address is lifted onto its own column, so a list clean gives you the address you should actually use rather than a nested suggestion.
- **Finds a person's other addresses.** Alternate email returns the other addresses tied to the same person or household, each with its own match type. That is how a bounced work address turns back into a reachable one.
- **Verifies phone numbers.** Phone verification returns line type, carrier, status, prepaid flag, country and a zero to one hundred connected score that says whether the line is actually live. Filter to mobile lines to build a list you can text.
- **Calls each route at the path it really answers on.** Three of these routes sit under a versioned path and two answer at the root. The versioned spellings of the last two are refused at the edge before they reach the API, so every route is written out in full rather than assembled from a shared prefix.
- **Keeps the key out of every log line.** This provider accepts the key only as a request parameter, never as a header, so the actor makes sure the real request URL is never written to a log.
- **Never charges for a miss.** Only rows carrying a resolved result are billed.

### Input

| Field | What it does |
| --- | --- |
| `mode` | Validate, demographics, email append, alternate email or phone verification. |
| `emails` | Addresses to validate, profile or find alternates for. |
| `ipAddresses` | Optional signup IPs, in the same order, to add geography. |
| `fullNames` | Names to append an address to. |
| `postalAddresses` | Postal addresses, paired line by line with the names. |
| `phones` | Numbers to verify. |
| `phoneCountry` | Two letter country code for numbers without a prefix. |
| `statuses` | Keep only these verdicts. |
| `domainTypes` | Keep only these domain categories. |
| `excludeRoleAccounts` | Drop shared inboxes such as info and support. |
| `minQualityScore` | Keep only addresses at or above this engagement score. |
| `lineTypes` | Keep only these phone line types. |
| `minConnectedScore` | Keep only numbers at or above this connected score. |
| `timeout` | Seconds the provider may spend on one address. |
| `requestsPerMinute` | Pace the run under your plan's rate limit. |
| `skipNotFound` | Leave unresolved inputs out of the dataset. |
| `maxResults` | Hard cap on rows, and therefore on spend and run time. |
| `apiKey` | Your own API key. Stored as a secret. |

### Example output

```json
{
  "found": true,
  "mode": "validate",
  "query": "jane.doe@example.com",
  "email": "jane.doe@example.com",
  "status": "safetosend",
  "statusCode": 50,
  "domain": "example.com",
  "domainType": "biz",
  "roleAccount": false,
  "qualityScore": 8,
  "correctedEmail": null,
  "emailCorrections": null,
  "ipCountry": "US",
  "ipStateProvince": "Massachusetts",
  "ipRoutingType": "fixed",
  "ipAddress": "99.110.204.1",
  "error": null,
  "raw": { }
}
```

### Frequently asked questions

#### What is an email append?

An email append matches a person you already know by name and postal address to the email address that belongs to them. It is the reverse of enrichment: instead of starting from an address and asking who owns it, you start from a household record and ask how to reach it by email. Every result carries a match type, which is the part that matters. An individual match means the full name and the postal address both matched. A household match means only the surname and the address matched, so the address may belong to someone else at the same home.

#### What demographics come back from an email address?

Age, gender, postcode, household income, net worth, home market value, home owner status, length of residence, marital status, presence of children, education, occupation, life stage group and segment, financial group and segment, and recency, frequency and spend history for both online and offline purchasing. Alongside those, the provider holds interest flags across dozens of categories; this actor returns the ones that matched as a list rather than spreading dozens of mostly empty columns across the table.

#### What is the difference between the safe to send verdict and valid?

Safe to send means the address passed every check the provider runs and is backed by its deliverability guarantee. Valid means it passed most of them but the mailbox itself could not be confirmed, usually because the receiving server would not answer a probe. Both are usually mailable, but only one carries the guarantee. Invalid means bad syntax, a dead domain or a mailbox that does not exist. Trap means the address is real but likely to trip a spam filter, and unknown means the checks could not be finished at all.

#### Can it correct a mistyped email address?

Yes. When an address fails only because of a spelling error the provider returns a corrected version, and the actor lifts the first correction into a `correctedEmail` column with every suggestion kept in `emailCorrections`. That is the difference between throwing away a signup and recovering it: a person who typed a common misspelling of a large webmail domain is a real subscriber with one bad character.

#### What does the connected score on a phone number mean?

It is the provider's confidence, from zero to one hundred, that the line is currently connected and dialable, and it is available for United States numbers. Above seventy means high confidence the number is live. Below thirty means high confidence it is disconnected. It is a different question from whether the number is valid: a number can be perfectly well formed, correctly routed to a real carrier, and still belong to a line that was cut off two years ago.

#### How do I build a list I can text rather than call?

Run phone verification, set the line type filter to mobile, and set a minimum connected score of seventy. That leaves only numbers on mobile lines that the provider is confident are still live. The carrier and prepaid flag come back on every row, which is worth keeping: prepaid lines change hands far more often than postpaid ones, so a prepaid number that verified today is a weaker record than a postpaid one.

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

Yes. This actor does not include data access. You use your own API key from AtData, which is the provider whose email intelligence API this actor calls, created on their dashboard. Your own plan, credit balance and terms apply. Paste the key into the `apiKey` field, where it is stored as an Apify secret. This provider accepts the key only as a request parameter and not as a header, so the actor makes sure the real request URL never reaches a log line.

#### How does this handle rate limits and spent credits?

Requests are spaced evenly across the minute so a long list does not bunch up against the limiter, and the pace is yours to set. A rate limit or server error response is retried with backoff, because it clears on its own. A rejected key and a spent quota are treated differently: this provider answers both with a bare line of text rather than a JSON object, so the actor reads the body as text first and reports the provider's own message rather than a parse failure, and it stops instead of burning retries on something waiting will not fix.

#### Why did every alternate email lookup come back empty?

Because that one route does not check the key. Four of the five lookups reject a bad key outright, but alternate email answers HTTP 200 with an empty body whether the provider genuinely knows no other address for that person or your key is simply not entitled to the route. There is no way to tell the two apart from the response, so the actor logs a warning when a whole run of alternate email lookups comes back empty. If that is unexpected, run the same key against the validation lookup, which will say plainly whether the key is being accepted.

#### What happens when a lookup matches nobody?

This provider answers a miss with a successful response carrying an empty body, not with an error. That is a real answer about the input, so the row is written with `found: false` and an `error` explaining which lookup came back empty, and the run continues. Misses are not charged for. Set `skipNotFound` to true to leave them out of the dataset entirely.

#### How much does a run cost?

Pricing is pay per result: you are charged for each address, person or phone number resolved into the dataset, and never for misses, for rows dropped by the filters, or for duplicates. Apify platform usage is included in the per-result price. Your own API provider's credit balance is separate and billed by them.

### Keyword map

email append API, email appending service, reverse append, demographic append API, consumer data append, household income data, net worth data, identity resolution, email validation API, email verification, safe to send, spam trap detection, role account detection, email typo correction, alternate email lookup, phone validation API, phone verification, line type lookup, carrier lookup, mobile number detection, connected score, data hygiene, customer data enrichment, direct mail list building

# Actor input Schema

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

Validate checks a list of addresses for deliverability and corrects typos. Demographics returns the household behind each address. Email append works out an address from a name and a postal address. Alternate email returns the other addresses belonging to the same person. Phone verification returns the line, carrier and connection status behind a number.

## `emails` (type: `array`):

Email addresses, one per line. Used by validation, demographics and alternate email. An address pasted inside a longer string, such as a mail header or a name and address pair, is extracted before the request.

## `ipAddresses` (type: `array`):

Optional IP addresses the matching address signed up from, one per line, in the same order as the addresses above. The provider uses them to add country, state and connection type to the record. Leave empty when you do not have them. Validation only.

## `fullNames` (type: `array`):

Full names to append an address to, one per line. Each name is paired with the postal address on the same line below, because an append needs both halves of one person. A middle name is understood, and the last word is treated as the surname. Email append only.

## `postalAddresses` (type: `array`):

One postal address per line, paired line by line with the names above, written as street, city, state, postcode. Both the four part and the three part spelling are understood, so 1 Main St, Boston, MA 02116 works as well as 1 Main St, Boston, MA, 02116. Email append only.

## `phones` (type: `array`):

Phone numbers to verify, one per line. Brackets, dots and spaces are stripped before the request, so a pasted list in mixed formats still works. Phone verification only.

## `phoneCountry` (type: `string`):

Two letter ISO country code for the numbers above, such as US or GB. Set it when your numbers are written in national format without a country prefix. Leave empty when every number carries its own prefix. Phone verification only. For example US.

## `statuses` (type: `array`):

Only keep addresses with these verdicts. Restricting to the safe to send verdict is how you turn a raw list into one that is ready to mail. Leave empty to keep every verdict. Validation only, and applied after the provider answers, so it reduces dataset noise and Apify spend rather than provider credits.

## `domainTypes` (type: `array`):

Only keep addresses whose domain falls into these categories. Restricting to business domains is the quickest way to strip consumer webmail out of a B2B list. Leave empty to keep every domain type. Validation only.

## `excludeRoleAccounts` (type: `boolean`):

Leave out shared inboxes such as info, sales and support, keeping only addresses that belong to an individual. Useful when the list is meant for one to one outreach. Validation only.

## `minQualityScore` (type: `integer`):

Only keep addresses scoring at least this on the provider's zero to ten engagement scale, which reflects how the mailbox behaves rather than whether it exists. Leave at zero to keep every score. Validation only.

## `lineTypes` (type: `array`):

Only keep numbers on these kinds of line. Restricting to mobile is how you build a list that can be texted. Leave empty to keep every line type. Phone verification only.

## `minConnectedScore` (type: `integer`):

Only keep numbers scoring at least this on the provider's zero to one hundred connected scale, which is its confidence that the line is live and dialable. Above seventy means high confidence it is connected. United States numbers only. Leave at zero to keep every score. Phone verification only.

## `timeout` (type: `integer`):

How long the provider may spend on one address before answering unknown. Raising it resolves more of the slow mail servers at the cost of a longer run. The provider's own ceiling is thirty seconds. Validation only.

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

Pace the run so it stays under whatever rate your plan allows. Lower this if the provider starts returning rate limit responses; raise it to finish a long list sooner.

## `skipNotFound` (type: `boolean`):

Leave inputs the provider had nothing for out of the dataset. Off by default, because keeping the misses is what lets you see which inputs resolved and which did not. Misses are never charged for either way.

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

Stop after this many rows. This is the cap on both spend and run time.

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

Your own API key for the email intelligence API. This provider accepts the key only as a request parameter, so the actor keeps it out of every log line instead. Required for every lookup. Stored as a secret.

## Actor input object example

```json
{
  "mode": "validate",
  "emails": [
    "jane.doe@example.com"
  ],
  "statuses": [],
  "domainTypes": [],
  "excludeRoleAccounts": false,
  "minQualityScore": 0,
  "lineTypes": [],
  "minConnectedScore": 0,
  "timeout": 10,
  "requestsPerMinute": 300,
  "skipNotFound": false,
  "maxResults": 100
}
```

# Actor output Schema

## `results` (type: `string`):

One row per address, person or phone number resolved, with the verdict, the appended identity and the provider's own reason codes.

# 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 = {
    "emails": [
        "jane.doe@example.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("nabeelbaghoor/email-append-demographics-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 = { "emails": ["jane.doe@example.com"] }

# Run the Actor and wait for it to finish
run = client.actor("nabeelbaghoor/email-append-demographics-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 '{
  "emails": [
    "jane.doe@example.com"
  ]
}' |
apify call nabeelbaghoor/email-append-demographics-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nabeelbaghoor/email-append-demographics-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/RWGvO2OvONH6KyDc7/builds/mGSamlKx4EPFTX81x/openapi.json
