# Username Search & Cross-Platform Identity Resolution (`nimbryxo-studio/username-search-and-cross-platform-identity`) Actor

Search usernames across 400+ social networks with target-network filtering, then confirm which account on a specific platform truly belongs to a known profile using transparent, signal-based confidence scoring.

- **URL**: https://apify.com/nimbryxo-studio/username-search-and-cross-platform-identity.md
- **Developed by:** [Nimbryxo-studio](https://apify.com/nimbryxo-studio) (community)
- **Categories:** Social media, Lead generation, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.49 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Username Search & Cross-Platform Identity Resolution

Find where a handle exists across hundreds of social networks, developer communities, forums, and niche sites — then work out which account on a target platform actually belongs to a profile you already know. Every hit is reported as a candidate with its own status and, when you ask for it, its public profile details. No login, no API key, no proxy setup.

Two workflows share one dataset:

- **Broad Search** sweeps a username across the supported network list and returns the profile URLs that survive verification.
- **Identity Resolution** takes a known source profile, finds or accepts candidates on one target network, and ranks them with a transparent signal breakdown.

### What this actor does

- **436 selectable networks** — GitHub, YouTube, TikTok, LinkedIn, Reddit, Steam, Bluesky, Mastodon instances, coding platforms, forums, gaming sites, and more. Pick a shortlist or sweep the safe default set.
- **Honest per-site status** — every checked site is counted as found, not found, blocked, error, invalid, or unreliable; blocked/rate-limited sites are named instead of silently disappearing.
- **Verification on by default** — each claimed profile is re-opened. Dead URLs are dropped; login walls and rate limits stay visible and flagged for review.
- **Optional profile details** — turn on `extractProfileFields` to add display name, bio, avatar, follower count, location, website, and join date where the source exposes them.
- **False-positive controls** — eight sites that returned random control handles as "found" in live testing are disabled in an unfiltered sweep; adult/NSFW sites are disabled by default too.
- **Identity scoring** — bio backlinks, display-name similarity, avatar similarity, verified badge, relative follower count, and username similarity are combined per candidate, with the full breakdown included.
- **Batch and wildcard input** — process up to 500 usernames per run when `maxUsernames` is raised; the default cap is 100 and truncation is reported in the status message and record warnings. `john{?}doe` expands to `john_doe`, `john-doe`, and `john.doe`. Rows are pushed as each username finishes, so a timeout keeps the completed rows.
- **Empty fields are omitted** — no `null`, no placeholder strings; every field present contains real data.

### Output: per username (mode = `broadSearch`)

One row per searched username:

- `username` — the handle that was searched
- `links[]` — profile URLs that passed the active checks
- `profiles[]` — per-site evidence, each with:
  - `siteName`, `siteMainUrl`, `profileUrl`, `finalUrl`
  - `status` — `found`, `unreliable`, `blocked`, `error`
  - `httpStatus`, `responseTimeMs`
  - `verificationStatus` — `verified`, `gated`, `missing`, `unverified`
  - `verificationRequired` — true when the result needs a human look
  - `unreliable` — present on known false-positive sites
  - optional `displayName`, `bio`, `avatarUrl`, `followers`, `location`, `websiteUrl`, `joinedAt`, `verified`
- `foundCount` — profile URLs in `links` (usable found profiles)
- `verifiedCount` — profiles that passed verification
- `checkedCount` — sites actually checked
- `statusCounts` — claimed found / verified / unreliable / notFound / blocked / error / invalid
- `searchMode` — `focused` when `targetNetworks` was supplied, otherwise `broad`
- `searchCompleted`, `partialFailure`, `sitesCheckedCount`
- `sitesRequested` — the shortlist you sent (omitted for a broad sweep)
- `sitesInvalid` — names the actor did not recognize
- `warnings[]` — non-fatal notes, including why a site could not be checked
- `sourceUrl` — the first profile URL in `links` (verified when verification is on), for traceability
- `recordType: "usernameSearch"`, `scrapedAt`

### Output: per target network (mode = `identityResolution`)

One row per target network:

- `sourceProfile` — `platform`, `handle`, `profileUrl`, `displayName`, `verified`, plus optional `bio`, `avatarUrl`, `followers`, `location`, `websiteUrl`, `joinedAt`, `sourceUrl`
- `targetNetwork`
- `candidateMode` — `discover` or `verify`
- `discoveryMethod` — `search`, `heuristic`, or `verify`
- `candidatesEvaluated`
- `bestMatch` — the highest-confidence candidate above `minConfidenceScore` **and** supported by at least one independent signal (or a verified profile), with `handle`, `profileUrl`, `confidenceScore`, `confidenceLabel`, `signals`, `profileExists`, `verificationStatus`, and the same optional profile fields
- `candidates[]` — every scored candidate, ranked by confidence, each with its own `signals` breakdown and `profileExists`/`verificationStatus`. A candidate the target network says does not exist is never a `bestMatch`; a username-only match is capped below `high`.
- `minConfidenceScore`, `partialFailure`, `sitesInvalid`
- `warnings[]` — missing source signals, unsupported discovery paths, or blocked candidates
- `sourceUrl`, `recordType: "identityResolution"`, `scrapedAt`

A candidate's `signals` object only contains the signals that could actually be computed. Missing signals are omitted, not zeroed; the score renormalizes over what remains.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `broadSearch` | `broadSearch` or `identityResolution` |
| `usernames` | array | – | Handles to search (mode=broadSearch). Accepts `@handle` and `{?}` wildcards. |
| `targetNetworks` | array | all safe sites | Shortlist of network names. Required for identityResolution; `verify` accepts exactly one. |
| `includeNsfw` | boolean | `false` | Include the 17 adult/NSFW sites in an unfiltered sweep. |
| `includeUnreliable` | boolean | `false` | Include the 8 sites with known false-positive behaviour; their results are flagged. |
| `verifyResults` | boolean | `true` | Re-open claimed profiles and drop dead URLs. Gated pages stay flagged. |
| `extractProfileFields` | boolean | `false` | Add public profile details where available (extra request per profile). |
| `maxUsernames` | integer | `100` | Usernames processed per broadSearch run (1–500). Truncation is reported in the status message and warnings. |
| `maxConcurrency` | integer | `2` | Usernames searched in parallel (1–5). |
| `requestTimeoutSecs` | integer | `20` | Per-site timeout for checks and verification (5–60). |
| `sourceProfile` | object | – | Known account for identityResolution, e.g. `{"platform":"github","handle":"torvalds"}` |
| `sourceOverrides` | object | – | Manual `displayName`, `bio`, or `avatarUrl` for the source profile. |
| `candidateMode` | string | `discover` | `discover` candidates automatically, or `verify` only the handles you supply. |
| `candidateHandles` | array | `[]` | Candidate handles for `verify` mode. |
| `maxCandidatesToDiscover` | integer | `20` | Candidate cap per target network (1–60). |
| `minConfidenceScore` | number | `0.3` | Minimum score for a `bestMatch` (0–1). |

Legacy keys from earlier versions are still accepted in code: `username`, `query`, `searchQuery`, `sites`, `networks`, `socials`, `platforms`, `profile`, `handles`, `maxCandidates`, `maxItems`, `maxResults`, `includeProfileDetails`, `verify`, `nsfw`, and `confidenceThreshold`. They are mapped onto the fields above; they do not need to be in your saved input.

#### Example: focused broad search with details

```json
{
  "mode": "broadSearch",
  "usernames": ["torvalds"],
  "targetNetworks": ["GitHub", "YouTube", "Reddit", "Medium"],
  "verifyResults": true,
  "extractProfileFields": true
}
```

#### Example: broad sweep with safe defaults

```json
{
  "mode": "broadSearch",
  "usernames": ["openai", "natgeo"],
  "verifyResults": true,
  "maxConcurrency": 2
}
```

#### Example: verify a shortlist on one network

```json
{
  "mode": "identityResolution",
  "sourceProfile": {"platform": "github", "handle": "torvalds"},
  "targetNetworks": ["GitHub"],
  "candidateMode": "verify",
  "candidateHandles": ["torvalds", "torvalds-official"],
  "minConfidenceScore": 0.5
}
```

#### Example: discover candidates automatically

```json
{
  "mode": "identityResolution",
  "sourceProfile": {"platform": "github", "handle": "torvalds"},
  "targetNetworks": ["GitHub"],
  "candidateMode": "discover",
  "maxCandidatesToDiscover": 20
}
```

#### Example: wildcard batch

```json
{
  "mode": "broadSearch",
  "usernames": ["john{?}doe", "jane_doe"],
  "targetNetworks": ["GitHub", "Bluesky", "Mastodon.social"],
  "maxUsernames": 10
}
```

### Use cases

- **Influencer and partnership vetting** — confirm which account belongs to a creator before committing spend.
- **Brand protection** — find lookalike and squatter accounts, and see the exact status of each site that was checked.
- **OSINT and investigations** — map a handle across social, coding, gaming, and forum communities with an auditable per-site trail.
- **Recruiting and vendor due diligence** — cross-check a candidate's public technical and social presence.
- **Digital-footprint audits** — discover forgotten accounts before a launch, job change, or privacy cleanup.
- **Dataset enrichment** — add verified profile URLs and optional public details to a lead or identity table.

### Data source and coverage

The actor ships a pinned snapshot of the [Sherlock project](https://github.com/sherlock-project/sherlock) site database (MIT License), taken on 2026-11-04. The snapshot contains 435 sites; the upstream project's own false-positive exclusions have already been removed. Reddit is added as a separate target and is checked through its public JSON endpoint. The actor is not affiliated with Sherlock or any of the networks it checks.

An unfiltered sweep checks the safe default set (410 sites): the 17 adult/NSFW sites and the 8 known-false-positive sites are skipped unless you opt in. Reddit is not part of the unfiltered sweep; target it explicitly to check it. A focused `targetNetworks` shortlist checks exactly the sites you name.

Identity resolution needs a username profile URL template. Discord, Diskusjon.no, and Kvinneguiden do not have one in the vendored site database, so identity mode skips those targets with a warning instead of inventing a URL. Broad search still checks them through their own existence probes.

### Limitations

- A matching username does **not** prove that two accounts belong to the same person. Treat broad-search hits as candidates and verify important findings at the source.
- Some sites block automated requests from datacenter IPs. They are reported as `blocked` (401/403/429/WAF), never silently treated as "not found".
- Profile details are best-effort. Many sites expose only a display name or bio; follower counts, locations, and join dates are available on fewer sites. Fields the page does not expose are omitted.
- The site database is a snapshot. A site that changes its markup after the snapshot date can produce a wrong status until the snapshot is refreshed.
- Reddit frequently rejects anonymous requests from cloud IP ranges. Its status is reported honestly; GitHub is the most reliable identity-resolution target.
- Adult/NSFW and known-false-positive sites are opt-in so the default output stays clean. Opting in is supported and clearly flagged.
- Avatar URLs are checked from a clean client before they are emitted. URLs that do not return an image are dropped rather than pushed as broken links; they are not rehosted.
- A broadSearch run stops starting new usernames after roughly 27 minutes so a large batch cannot burn the whole run timeout. Completed rows are already in the dataset; skipped rows carry a warning.
- Existence sweeps retry transient 429/471/5xx responses in bounded batches, then stop retrying after repeated blocks instead of hammering a WAF.

### FAQ

#### How is this different from a plain Sherlock run?

A plain Sherlock run prints URLs. This actor adds verification, per-site statuses, optional public profile details, false-positive controls, and an identity-resolution mode that ranks candidates on independent signals. It also gives you a machine-readable dataset instead of console text.

#### Do I need cookies, an API key, or a proxy?

No. The actor only requests public pages and public JSON endpoints. There is no credential field and no proxy configuration to fill in.

#### Why are some sites missing from my results?

If you sent `targetNetworks`, only those sites were checked. In an unfiltered sweep, adult/NSFW sites and the eight known-false-positive sites are skipped by default. Set `includeNsfw` or `includeUnreliable` to include them.

#### What do the per-site statuses mean?

`found` means the site's existence rule claimed the handle. `unreliable` means the site is known to claim random handles. `blocked` means the site returned 401/403/429 or a WAF page. `error` means a timeout or network failure. `invalid` means the handle cannot exist on that site because it fails the site's own username pattern.

#### Why does a profile have no display name or avatar?

The optional fields are extracted only when the public page exposes them. Login walls, JavaScript-only pages, and sites without OpenGraph/JSON-LD metadata often provide nothing. The actor omits missing fields instead of inventing values.

#### What does `verifyResults` actually check?

It re-requests each claimed profile URL. A 404/410 is marked `missing` and dropped from `links`. A 401/403/429 or a login redirect is marked `gated` and kept visible with `verificationRequired: true` at the claimed URL (the redirect target is kept separately in `finalUrl`). A 200 page is marked `verified` only when it has real profile evidence: a canonical handle path plus profile metadata, or Person/ProfilePage JSON-LD that names the handle. A soft-404 ("Page not found"), a login wall, or a generic page with the handle merely somewhere in the URL is `unverified`, not `verified`.

#### How does identity resolution decide on a best match?

Each candidate is scored on the signals that can be computed: bio backlink, display-name similarity, avatar similarity, verified badge, follower count relative to the other candidates, and username similarity. The weighted score is shown per candidate. In `verify` mode every candidate is existence-checked on the target network first; a 404 lookalike is reported with `profileExists: false` and can never become `bestMatch`. `bestMatch` is only emitted when the top score reaches `minConfidenceScore` and the candidate has independent evidence (a non-username signal or a verified profile). A username-only match is capped below `high` confidence.

#### Why is my target network not in the dropdown?

The dropdown is generated from the pinned site snapshot plus Reddit. If a network is absent, it was not in the snapshot or was one of the upstream false-positive exclusions. You can still supply it as a candidate target only if it is recognized; unknown names are reported in `sitesInvalid`.

#### Can I search private or deleted accounts?

No. Only public pages are requested. Private, deleted, and restricted profiles are not accessible.

#### Can I export the dataset?

Yes. Apify datasets export to JSON, CSV, Excel, HTML, XML, and RSS from the console or API.

#### Is this affiliated with the networks it checks?

No. This is an independent third-party actor using publicly accessible information. It is not affiliated with GitHub, Reddit, TikTok, Instagram, Twitter/X, LinkedIn, YouTube, Sherlock, or any other site in the database.

# Actor input Schema

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

broadSearch: check usernames across networks (optionally filtered) and return every found profile with its status. identityResolution: disambiguate which candidate account on a target network matches a source profile.

## `usernames` (type: `array`):

Usernames to search for (mode=broadSearch). Accepts one to 500, but only maxUsernames (default 100) are processed per run; the status message and record warnings report any shortfall. Supports the {?} wildcard (e.g. 'john{?}doe' expands to 'john_doe', 'john-doe', 'john.doe'). A leading @ is ignored. The legacy single `username` field is still accepted.

## `targetNetworks` (type: `array`):

Limit the search/resolution to these networks. Omit to check the 410-site safe sweep (435 vendored sites minus 17 adult/NSFW and 8 known-false-positive sites; Reddit is only checked when explicitly targeted). In identityResolution this field is required; candidateMode 'verify' requires exactly one network. Discord, Diskusjon.no, and Kvinneguiden are skipped with a warning in identity mode because the site database has no username profile URL template for them. Reddit is checked through its public JSON endpoint.

## `includeNsfw` (type: `boolean`):

When no targetNetworks are supplied, also check the 17 adult/NSFW sites in the site database. Off by default.

## `includeUnreliable` (type: `boolean`):

When no targetNetworks are supplied, also check the 8 sites that reported random control handles as found in live testing. Their results are marked unreliable. Off by default.

## `verifyResults` (type: `boolean`):

Re-open each found profile page. broadSearch drops dead URLs and keeps gated pages flagged; identityResolution marks every candidate with profileExists/verificationStatus and only emits a bestMatch supported by independent evidence or a verified profile. Soft-404 and login pages are never marked verified. Adds one request per found profile. On by default.

## `extractProfileFields` (type: `boolean`):

Opt in to public profile details (display name, bio, avatar, location, follower count where the source exposes them) in both modes. Identity resolution always fetches what it needs for scoring, but emits the optional detail fields only when this is on. Adds one request per found profile. Off by default; empty and unverifiable avatar URLs are omitted.

## `maxUsernames` (type: `integer`):

How many usernames a broadSearch run will process. Defaults to 100; raise it to 500 for larger batches. When input is truncated, the status message and each record's warnings state how many usernames were skipped.

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

How many usernames are searched at the same time in broadSearch. Lower this on a small-memory run.

## `requestTimeoutSecs` (type: `integer`):

Per-site timeout for existence checks and profile verification.

## `sourceProfile` (type: `object`):

The known account to resolve against (mode=identityResolution). Example: {"platform": "github", "handle": "torvalds"}. The legacy `profile` key is still accepted.

## `sourceOverrides` (type: `object`):

Optional manual displayName/bio/avatarUrl for the source profile, used when the source platform cannot be read or to supplement missing data.

## `candidateMode` (type: `string`):

discover: auto-generate candidates via search + username-variation heuristics. verify: score only the candidateHandles you supply.

## `candidateHandles` (type: `array`):

Handles to verify against the source profile on the single target network (required when candidateMode is 'verify'). Capped at 60 to keep existence checks bounded. The legacy `handles` key is still accepted.

## `maxCandidatesToDiscover` (type: `integer`):

Upper bound on generated/searched candidates per target network in discover mode.

## `minConfidenceScore` (type: `number`):

A candidate becomes bestMatch only when its confidence score reaches this value (0-1). Lower it to see weaker matches; raise it for stricter matching.

## Actor input object example

```json
{
  "mode": "broadSearch",
  "usernames": [
    "torvalds"
  ],
  "targetNetworks": [
    "GitHub"
  ],
  "includeNsfw": false,
  "includeUnreliable": false,
  "verifyResults": true,
  "extractProfileFields": false,
  "maxUsernames": 1,
  "maxConcurrency": 1,
  "requestTimeoutSecs": 15,
  "sourceProfile": {
    "platform": "github",
    "handle": "torvalds"
  },
  "candidateMode": "discover",
  "candidateHandles": [],
  "maxCandidatesToDiscover": 20,
  "minConfidenceScore": 0.3
}
```

# Actor output Schema

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

Dataset containing all username search and identity resolution records.

# 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 = {
    "mode": "broadSearch",
    "usernames": [
        "torvalds"
    ],
    "targetNetworks": [
        "GitHub"
    ],
    "includeNsfw": false,
    "includeUnreliable": false,
    "verifyResults": true,
    "extractProfileFields": false,
    "maxUsernames": 1,
    "maxConcurrency": 1,
    "requestTimeoutSecs": 15,
    "sourceProfile": {
        "platform": "github",
        "handle": "torvalds"
    },
    "candidateMode": "discover",
    "candidateHandles": [],
    "maxCandidatesToDiscover": 20,
    "minConfidenceScore": 0.3
};

// Run the Actor and wait for it to finish
const run = await client.actor("nimbryxo-studio/username-search-and-cross-platform-identity").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 = {
    "mode": "broadSearch",
    "usernames": ["torvalds"],
    "targetNetworks": ["GitHub"],
    "includeNsfw": False,
    "includeUnreliable": False,
    "verifyResults": True,
    "extractProfileFields": False,
    "maxUsernames": 1,
    "maxConcurrency": 1,
    "requestTimeoutSecs": 15,
    "sourceProfile": {
        "platform": "github",
        "handle": "torvalds",
    },
    "candidateMode": "discover",
    "candidateHandles": [],
    "maxCandidatesToDiscover": 20,
    "minConfidenceScore": 0.3,
}

# Run the Actor and wait for it to finish
run = client.actor("nimbryxo-studio/username-search-and-cross-platform-identity").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 '{
  "mode": "broadSearch",
  "usernames": [
    "torvalds"
  ],
  "targetNetworks": [
    "GitHub"
  ],
  "includeNsfw": false,
  "includeUnreliable": false,
  "verifyResults": true,
  "extractProfileFields": false,
  "maxUsernames": 1,
  "maxConcurrency": 1,
  "requestTimeoutSecs": 15,
  "sourceProfile": {
    "platform": "github",
    "handle": "torvalds"
  },
  "candidateMode": "discover",
  "candidateHandles": [],
  "maxCandidatesToDiscover": 20,
  "minConfidenceScore": 0.3
}' |
apify call nimbryxo-studio/username-search-and-cross-platform-identity --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nimbryxo-studio/username-search-and-cross-platform-identity"
        }
    }
}
```

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/7YG0FwvsFroVAXASN/builds/rPvz7EtWwiYuE2ZpM/openapi.json
