# Email OSINT Lookup - Find Accounts, Breaches & Identity (`s-r/apifyosintemail`) Actor

Email OSINT for investigators, fraud and security teams: check which of 133 platforms an address is registered on, get the name and profile links behind it, its data breach history and an A-F risk score. One row per account found; pay only for found accounts.

- **URL**: https://apify.com/s-r/apifyosintemail.md
- **Developed by:** [SR](https://apify.com/s-r) (community)
- **Categories:** Lead generation, Social media, Developer tools
- **Features:** Limited permissions
- **Stats:** 3,554 total users, 167 monthly users, 99.5% runs succeeded, 9 bookmarks
- **User rating**: 4.31 out of 5 stars

## Pricing

from $10.40 / 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?

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

## Email OSINT Lookup

Email OSINT lookup for investigators, fraud teams and security researchers. Give
it an email address; it finds the accounts registered to it on 133 platforms,
who the address belongs to, and which data breaches it has been exposed in.

Only definitive account findings become dataset rows. Checks that cannot complete
are reported as `unknown`, never as "no account". Checks that require sending
login or recovery email, or creating an account, are also left unresolved. A source
that does not answer must not become a confident negative.

### What this email OSINT lookup returns

#### Identity enrichment

Not just a yes/no. Where the data exists, you get a name and real profile URLs.

| Source | Returns |
|---|---|
| **Gravatar** | Real name, location, job title, and verified **LinkedIn / X / GitHub / Instagram** profile URLs |
| **GitHub** | GitHub username and profile resolved from commit authorship |

#### Account detection

| Group | Platforms |
|---|---|
| **Learning & education** (19) | Alison, Allen, Asafeer, Aslbloom, Babbel, Bnrlanguages, Bunpo, Cakeapp, Cambly, Classdojo, Coursera, Duolingo, Hanzii, Hellochinese, Heyjapan, Programminghub, Quizlet, Talkpal, Vedantu |
| **Developer & tech** (18) | Codecademy, Codewars, Devrant, Envato, Hackerearth, Hackerone, Hackerrank, Hackthebox, Howtogeek, Huggingface, Luarocks, Medium, Qiita, Rubygems, Wix, Wondershare, Wordpress, Xda |
| **Social** (14) | Classmates, Couplejoy, Facebook, Instagram, Locket, Lovenudge, Mastodon, Meeff, Mewe, Pinterest, Plurk, Slowly, Whering, X |
| **Entertainment** (11) | Anilist, Appletv, Dreame, Girlslife, Hoichoi, Justwatch, Myanimelist, Nebula Tv, Stremio, Sunnxt, Weverse |
| **Shopping & commerce** (11) | Amazon, Etsy, Fixderma, Flipkart, Hautesauce, Naturabuy, Nykaaman, Rappi, Tatacliq, Vivino, Walmart |
| **Productivity & other** (10) | Anydo, Dragongroot, Dropbox, Eventbrite, Firefox, Moz, Numsify, Office365, Screener, Secondline |
| **Creator & design** (8) | Adobe, Buymeacoffee, Canva, Figma, Flickr, Kick, Patreon, Vimeo |
| **News & media** (7) | Aljazeera, Bbc, Cnn, Flipboard, Foxnews, Globaltimes, Indiatimes |
| **Sports** (7) | Aiscore, Besoccer, Espn, Marca, Nba, Playtomic, Uniscore |
| **Fitness** (5) | Evolveyou, Finch, Fitnessblender, Myfitnesspal, Sweat |
| **Music** (5) | Deezer, Gaana, Jiosaavn, Mixcloud, Spotify |
| **Gaming** (4) | Addictinggames, Chess Com, Crazygames, Stackb |
| **CRM** (3) | Axonaut, Insightly, Zoho |
| **Dating** (3) | Lespark, Okcupid, Skout |
| **Travel** (3) | Komoot, Polarsteps, Skyscanner |
| **Community** (2) | Disqus, Nextdoor |
| **Hosting** (2) | Neocities and one CDN hosting provider |
| **Jobs** (1) | Freelancer |

#### Email analysis

Format validation, disposable detection, free-provider detection, business-domain
detection, role-account detection (`info@`, `admin@`), and name hints.

#### Security intelligence

Breach history and an A–F risk score based on exposure and account activity.

### Input

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `emails` | string\[] | Yes | None | Addresses to investigate, one per line |
| `max_results_per_email` | integer | No | `25` | Cap on sources reported per address. You are billed per found source, so this is your cost ceiling per address. `0` disables it |
| `follow_handles` | boolean | No | `false` | Follow at most 3 distinct verified handles per address; paid plans only. Adds checker-run charges described below |
| `max_concurrency` | integer | No | `10` | Emails processed at once (1–10) |

A run processes at most five addresses; anything beyond the first five is not
looked up. Split larger lists across runs. A minimal input:

```json
{
  "emails": ["beau@dentedreality.com.au"],
  "max_results_per_email": 25
}
```

### Output

The dataset holds **one row per channel where the address was found**. A row
says one thing, so it reads as a table and exports straight to CSV:

| email | channel | found | username | profile_url |
|---|---|---|---|---|
| beau@dentedreality.com.au | amazon | true | null | null |
| beau@dentedreality.com.au | anydo | true | null | null |
| beau@dentedreality.com.au | gravatar | true | Beau Lebens | https://gravatar.com/beau |

`username` and `profile_url` are filled for the channels that expose them and
null elsewhere, so the columns stay stable. These example rows were retrieved
from the address shown; results can change as source availability changes.

Per-address context is identical on every row, so it is not repeated there.
Two records accompany the run instead:

- **`FULL_RESULTS`** — one complete record per address: email analysis, every
  breach with its exposed-data categories, the full channel map, and every
  unresolved check.
- **`NO_RESULTS`** — addresses where nothing was found, and separately any
  address whose lookup *failed*. A failed lookup is not the same as finding
  nothing: nothing is known about it. Neither produces rows and neither is
  billed.

For the same example address, the summary in `FULL_RESULTS` read:

```json
{
  "summary": {
    "accounts_found": 11,
    "accounts_checked": 101,
    "accounts_unresolved": 38,
    "is_active_email": true,
    "risk_score": "B"
  },
  "breach_info": {
    "breached": true,
    "breach_count": 31,
    "risk_label": "High",
    "risk_score": 73
  }
}
```

Each breach entry carries its name, year, industry, whether it is verified and
the exposed data categories (for example "Dates of birth"). Passwords are never
returned.

### Use cases

- **Fraud prevention.** A sign-up address with no footprint anywhere, a
  disposable domain and no breach history is a different risk from one with a
  decade of accounts. Use the email OSINT result as one signal in a review queue.
- **Investigations and due diligence.** See where an address is registered and
  which public identity sits behind it: a Gravatar name, location, job title and
  linked LinkedIn, X, GitHub or Instagram profiles.
- **Security awareness.** Check staff or customer addresses for breach exposure
  and see which categories of data leaked, without ever handling a password.
- **Account takeover triage.** A high breach count combined with many active
  accounts tells you which users to prompt for a password reset first.

### Email OSINT compared with other tools

Open-source tools such as holehe answer one question per platform: is this
address registered? Running them yourself means installing Python, keeping the
modules working as sites change, and reading terminal output. This actor runs
the same kind of account checks as a hosted batch job, and adds three things
in the same run:

| | This actor | A plain account checker | A breach checker |
|---|---|---|---|
| Accounts on 133 platforms | Yes | Yes | No |
| Name and linked profiles (Gravatar, GitHub) | Yes | No | No |
| Breach history with exposed-data categories | Yes | No | Yes |
| A–F risk score | Yes | No | Sometimes |
| Unknown kept separate from "no account" | Yes | Often not | Not applicable |
| Billing | Per account found | Varies | Per address |

The distinction between `unknown` and "no account" matters most. A check that
times out or is rate-limited is listed in `accounts_unknown`, so you never read a
dead source as a clean negative.

### Pricing

**You are billed per found source, not per address.** If an address turns up
five sources, you pay for five. If it turns up nothing, there is no found-source charge. The existing actor-start
fee still applies.

Use `max_results_per_email` to set a hard ceiling per address. It defaults to
25, which covers a typical address comfortably while stopping a heavily-used
one from returning 80+ billable channels. When the cap truncates, direct email
findings take priority over handle candidates. Within each group, rows that
carry an identity (username, profile URL) are kept in preference, and the run
reports that the channel limit was reached. `FULL_RESULTS` always holds the
complete channel map, so nothing is hidden by the cap.

| Event | Price | When it fires |
|---|---|---|
| **Found source** (main) | $0.0104 | Once for each source an address was found on |
| Actor start | $0.00005 | Per GB of run memory, minimum one event |

Two things are never billed:

- **Unknowns.** A check that could not complete is not a found source.
- **Unreliable sources.** A check that cannot tell a real address from an
  impossible one never produces a finding, so it never charges.

### Notes

- Checks that would send a login or recovery message, or create an account,
  remain unresolved. They do not produce a billed finding.
- The account scan runs for every valid address. Availability varies by
  platform; the unresolved-check list describes what could not be determined.
- Duration depends on source availability and the number of addresses. A
  lookup that exceeds its time budget is recorded as failed and does not bill.
- Use this for lawful investigation, fraud prevention, due diligence and
  security research only.

### Free-plan limits

Users without a paid Apify plan receive at most ten channel rows across the
entire run. The per-address limit is also bounded for those runs, including
when the requested value is zero. The complete analysis remains available in
`FULL_RESULTS`. Paid users retain the requested limit and can use zero for
unlimited channel rows per address.

### FAQ

#### Is this email OSINT lookup visible to the person being investigated?

No. No email is sent to the address, no account is created and no password
reset is triggered. Checks that would require that are left unresolved.

#### How many addresses can I look up per run?

Up to five. Start several runs, or call the actor from the API in a loop, for
longer lists.

#### What happens when no accounts are found?

The address produces no dataset rows and no found-source charges. Its completed
analysis remains in `FULL_RESULTS`, and `NO_RESULTS.addresses` lists it.

#### Does unknown mean that no account exists?

No. It means the check did not produce a definitive answer. Unknown checks
remain separate from positive and negative verdicts and are never billed.

#### Does limiting rows remove the full analysis?

No. The per-address channel limit applies to dataset rows. `FULL_RESULTS`
retains the complete analysis, public identity, breach metadata and unresolved
checks. Rows with a name or profile URL are preferred when the limit applies.

### Optional handle follow-up

Enable `follow_handles` to check up to three distinct handles per address with
[Cross-platform Handle Checker](https://apify.com/s-r/cross-platform-handle-checker).
Handles come only from visible Gravatar verified accounts, GitHub commit
authorship, or profile URLs from found accounts. Names and email address
fragments are never guessed into usernames. Repeated evidence for the same
handle is combined. The checker uses its current default site list, including
new sites when its next release goes live.

Direct email findings carry `_type: "email_account"`. Found profiles from the
checker add rows with `_type: "handle_presence"`, `queried_handle`, `handle_origin`,
`match_type: "handle_candidate"`, and `email_link_verified: false`. A matching
username on another site is a candidate connection, not proof that the mailbox
owner controls it. All checker responses are retained in
`FULL_RESULTS[].handle_checks`, including summaries and negative results.
Failed, blocked, or timed out checks are `unknown`, never "no account".
Only newly found profiles add parent dataset rows. A profile that already proved
the handle, or a platform already delivered as a direct email finding, adds no
extra candidate row. Its complete check remains in `handle_checks`. The
per-address result cap covers both original channels and added candidates,
keeping direct email findings first; complete checks remain available in
`FULL_RESULTS` even when those rows are capped.

Handle follow-up is available on Apify. Other API channels return the ordinary
email results and a warning when `follow_handles` is enabled.

#### Handle follow-up pricing

This option is off by default and disabled for free-plan users. The checker runs
on your Apify account with the token of this run. Its current price is **$0.02
per handle plus $0.012 per checked platform**. With the current ten sites, this
is **$0.14 per distinct handle**, up to **$0.42 per address** for three handles.
These child-run charges are additional to this Actor's existing **$0.0104 per
delivered dataset row** and existing start fee. Child checks can incur charges
even when they find no profile or cannot resolve a platform. No unknown check
adds a charged row to this Actor's dataset. New checker sites or pricing can
change the follow-up cost; consult the linked checker's current pricing.

`max_results_per_email` caps rows delivered here, not the cost of child checks
already performed. A run with no verified handle starts no checker. Public
profiles only; the option does not log in, create accounts, trigger recovery
messages, or return breached data contents.

# Actor input Schema

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

Email addresses to investigate, one per line. Maximum 5 per run; anything beyond the first 5 is not processed. Split larger lists across runs.

## `max_results_per_email` (type: `integer`):

Maximum channel rows delivered per address, including optional handle candidates. This caps this Actor's row charges, not child checker charges already incurred by follow_handles. Set 0 for no row cap.

## `max_concurrency` (type: `integer`):

Maximum number of emails processed at once (1-10).

## `cursor` (type: `string`):

Continuation cursor returned as next_cursor. Send it with the original input until next_cursor is null.

## `follow_handles` (type: `boolean`):

Apify only: follow up to 3 distinct handles per email from verified public profile links or GitHub commit authorship using s-r/cross-platform-handle-checker. Additional child-run and delivered-row charges apply; disabled for free users. Other channels return ordinary email results with a warning.

## Actor input object example

```json
{
  "emails": [
    "beau@dentedreality.com.au"
  ],
  "max_results_per_email": 25,
  "max_concurrency": 10,
  "follow_handles": false
}
```

# 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 = {
    "emails": [
        "beau@dentedreality.com.au"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("s-r/apifyosintemail").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": ["beau@dentedreality.com.au"] }

# Run the Actor and wait for it to finish
run = client.actor("s-r/apifyosintemail").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": [
    "beau@dentedreality.com.au"
  ]
}' |
apify call s-r/apifyosintemail --silent --output-dataset

```

## MCP server setup

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

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/MUF85JoqnH8dgVXUr/builds/PNg187sA2LhkSRyoU/openapi.json
