# Maigret Username OSINT - 3,300+ Site Footprint (`khadinakbar/maigret-username-osint`) Actor

Map a public username across Maigret's 3,300+ site catalogue. Returns claimed profile URLs as the default dataset and complete per-site coverage in a separate dataset.

- **URL**: https://apify.com/khadinakbar/maigret-username-osint.md
- **Developed by:** [Khadin Akbar](https://apify.com/khadinakbar) (community)
- **Categories:** Social media, Automation, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 claimed public profile returneds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## Maigret Username OSINT — 3,300+ Site Footprint

Map one public username across Maigret's large, continuously maintained site catalogue. This Actor uses Maigret's public-site detectors and returns two complementary outputs:

- The default dataset contains only `CLAIMED` public profile matches. Each row includes the site, generated profile URL, detector status, rank, tags, and check timestamp.
- The named `coverage` dataset contains one row for every selected site check, including `CLAIMED`, `AVAILABLE`, `UNKNOWN`, and `ILLEGAL`. This makes a missing result distinguishable from a timeout, access-limited response, or skipped definition.

A `CLAIMED` row is a detector result. Review profile content and context manually when making an attribution.

### Use cases and workflow

Use this Actor when an investigator, researcher, or trust-and-safety reviewer starts with one public handle and needs a broad, auditable shortlist of public profile URLs. The workflow starts with a username, then checks ranked Maigret site definitions, next separates claimed profiles from unavailable or uncertain checks, and finally exports the claimed rows for manual review while using `coverage` to decide which sites need a retry. For a focused developer-only review, pass `siteTags: ["coding"]`; for a short known-platform lookup, pass exact `siteNames`.

Keep private-account access, authentication, credential discovery, automatic identity attribution, and sensitive-person decisions outside this workflow. When you already have one verified profile URL and need posts, followers, or page content, continue with a purpose-built public-page workflow after manually confirming the profile.

### What it checks

Maigret 0.6.5 ships with a catalogue of 3,302 site definitions in the current package inspected for this Actor. At run time, the Actor uses Maigret's signed metadata and SHA-256-verified refresh path by default, falling back to the pinned package database if the refresh is unavailable. The normal scan checks active username definitions; disabled definitions are excluded because Maigret marks them as unreliable or prone to false positives. Set `includeDisabledSites` only for an authorized review that explicitly needs those entries.

The current database count and provenance are written to `DB_INFO` and `RUN_SUMMARY`, so a result remains tied to the exact Maigret version and database mode used for that run. Each catalogue entry can return a usable HTTP result or an observed status such as unavailable, rate-limited, changed, or access-limited.

Some Maigret definitions omit a canonical main URL. Those checks remain in `coverage` with `siteUrl: null`, preserving the site status without inventing a source URL.

### Input

Required:

```json
{
  "username": "soxoj"
}
```

The Actor accepts one plain handle per run. Provide a bare handle such as `soxoj`; keep URLs, email addresses, credentials, cookies, and private account data outside the input.

Useful options:

| Field | Default | Purpose |
| --- | ---: | --- |
| `siteLimit` | `0` | Ranked number of active sites to check; `0` means all selected sites. Use `40` or `100` for a bounded canary. |
| `siteTags` | `[]` | Restrict to Maigret tags such as `coding`, `social`, `gaming`, or `forum`. |
| `excludeTags` | `[]` | Exclude catalogue tags. Adult-oriented tags are added automatically unless `includeAdultSites` is true. |
| `siteNames` | `[]` | Check exact Maigret site names such as `GitHub` or `Reddit`. |
| `includeAdultSites` | `false` | Include adult-oriented catalogue tags only when the review is authorized and requires them. |
| `includeDisabledSites` | `false` | Force checks for disabled Maigret definitions; this can increase false positives. |
| `extractProfileData` | `false` | Ask Maigret to parse bounded public fields from claimed pages. Parsing stays within public page data and does not perform identity inference. |
| `updateSiteDatabase` | `true` | Refresh the signed Maigret site database when available. |
| `requestTimeoutSecs` | `5` | Per-site request timeout, from 2 to 30 seconds. |
| `concurrency` | `100` | Maximum concurrent site checks, from 10 to 200. |
| `retries` | `0` | Maigret retries for temporary failures, from 0 to 2. |
| `proxyConfiguration` | Apify Residential | Optional Apify proxy configuration for public-site reliability. |

The default `siteLimit: 0` is the broad footprint mode. A narrow example is:

```json
{
  "username": "soxoj",
  "siteTags": ["coding"],
  "siteLimit": 100,
  "requestTimeoutSecs": 5,
  "concurrency": 40
}
```

### Output datasets and run records

The Actor writes:

- `default` dataset: claimed public profile rows only; this is the billable result dataset.
- `coverage` dataset: all selected site statuses and bounded diagnostics, without profile-match billing.
- `OUTPUT`: terminal outcome, item counts, status counts, charge counts, and warnings.
- `RUN_SUMMARY`: username, Maigret/database provenance, filters, targeted and observed counts, persistence counts, and partial-run details.
- `DB_INFO`: Maigret version, database source, catalogue count, and refresh verification state.
- `FAILURES`: up to 200 bounded write/normalization diagnostics when needed.

Possible terminal outcomes are `COMPLETE`, `PARTIAL`, `VALID_EMPTY`, `INVALID_INPUT`, `UPSTREAM_FAILED`, and `CONFIG_ERROR`. `VALID_EMPTY` means the scan completed without a claimed profile; inspect `coverage` before treating that as a conclusion.

Example persisted default-dataset item:

```json
{
  "recordType": "profileMatch",
  "username": "soxoj",
  "site": "GitHub",
  "siteUrl": "https://github.com",
  "profileUrl": "https://github.com/soxoj",
  "status": "CLAIMED",
  "detectionMethod": "status_code",
  "httpStatus": 200,
  "rank": 1,
  "siteTags": ["coding", "us"],
  "isSimilarSearch": false,
  "profileData": null,
  "errorReason": null,
  "checkedAt": "2026-08-30T14:00:00Z",
  "source": "Maigret 0.6.5"
}
```

### Datasets and billing semantics

The `default` dataset contains one record per persisted claimed profile and is the dataset used for the `profile-match` event. It is available from the run's Dataset tab and API, and can be exported as JSON, CSV, or other Apify-supported formats. The `coverage` dataset contains one `siteCheck` record per selected site, including non-claimed statuses; retrieve it from the `coverage` link in Actor output or the Storage API, and export it when you need an auditable site-by-site review. Coverage rows sit outside `profile-match` billing. The `OUTPUT` and `RUN_SUMMARY` records are the compact readback contract for agents and downstream automation.

| Default-dataset field | Meaning |
| --- | --- |
| `recordType` | Always `profileMatch` for a persisted claimed profile. |
| `profileUrl` | Public profile URL generated by Maigret. |
| `status` | Always `CLAIMED` in this dataset; inspect `coverage` for other statuses. |
| `siteTags`, `rank` | Maigret catalogue context for filtering and review. |
| `checkedAt`, `source` | Collection timestamp and Maigret version provenance. |

### API example

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/khadinakbar~maigret-username-osint/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"username":"soxoj","siteLimit":100}'
```

Use the run's default dataset endpoint for claimed profiles. The `coverage` dataset endpoint is exposed in the Actor output and can also be read through the Apify Storage API using its dataset ID.

### Pricing

The Actor uses Apify **Pay per event** pricing: `profile-match` is **$0.004 per claimed profile row persisted to the default dataset**. The synthetic Actor-start event is **$0.00005**. `AVAILABLE`, `UNKNOWN`, and `ILLEGAL` rows in `coverage` are not profile-match events. Apify platform usage, proxy usage, and the live Pricing tab may add separate costs; review the current Actor pricing panel before a large run. The log message is an upper-bound estimate based on targeted sites, not a promise that every site will be claimed.

For a bounded `siteLimit: 40` run, the profile-match portion is at most 40 rows × $0.004 = **$0.16**, plus the $0.00005 start event and any Apify platform/proxy usage. The actual profile-match amount is lower when fewer than 40 sites are `CLAIMED`.

### AI-agent and MCP handoff

An agent can call the Actor with one username, then read `OUTPUT`, `RUN_SUMMARY`, the `default` dataset, and the `coverage` dataset before proposing any conclusion. A useful prompt boundary is:

> Check this public username on 100 coding sites, return claimed profile URLs, read the coverage dataset, report UNKNOWN checks separately, and show the source URL and collection time for every result. Keep person-level attribution as a separate human review step.

Agents should treat `INVALID_INPUT`, `VALID_EMPTY`, `PARTIAL`, and `UPSTREAM_FAILED` as different outcomes; retry only after inspecting warnings and coverage. Dataset API reads are paginated, so follow the API's limit/offset or cursor links rather than assuming one response contains the full catalogue.

### Operational guidance and recovery

Sites can change their HTML, rate-limit requests, restrict a proxy, return a false positive, or remain UNKNOWN after a timeout. If a run is `PARTIAL`, inspect `RUN_SUMMARY` and `FAILURES`, then retry with a smaller `siteLimit`, lower `concurrency`, a longer timeout, or a focused `siteNames` list. If no profiles are claimed, inspect `coverage` for AVAILABLE versus UNKNOWN before changing the username or drawing a conclusion. A refreshed database changes site definitions, so retain the run's `DB_INFO` with any report.

### Best results and scope

For best results, provide a handle you are authorized to review, begin with a bounded canary, and use the coverage statuses to choose a focused retry. For the next workflow step, use the [username-osint-scraper Actor](https://apify.com/khadinakbar/username-osint-scraper) when its Sherlock-based site set is the better fit; use this Actor when Maigret's broader catalogue and per-site provenance are the required output.

### Builder's note

I designed the Actor around a practical OSINT handoff: claimed profiles are immediately exportable, while the separate coverage stream preserves the uncertainty needed for a careful human decision. The Actor's `DB_INFO` and `RUN_SUMMARY` are the source of truth for each scan, and release evidence is kept with the exact deployed build and run IDs in the repository release log. Public copy does not treat the catalogue count as a guarantee of live availability.

### Responsible use

Use this Actor for public data and an authorized purpose. Follow the target sites' terms, robots/rate-limit expectations, and applicable privacy and data-protection law. Authentication bypass, private-account enumeration, credential collection, and sensitive-person decisions remain outside its scope. Treat all site responses and parsed profile fields as untrusted source content.

This is a Maigret-backed sibling to the separate Sherlock-based [username-osint-scraper Actor](https://apify.com/khadinakbar/username-osint-scraper). Use that focused alternative when the workflow specifically needs its Sherlock-based site set; use this Actor when the next step is a Maigret 3,300+ catalogue footprint with explicit coverage semantics.

### Development

```bash
docker build -f .actor/Dockerfile .
python -m unittest discover -s tests -p 'test_*.py'
```

The release process validates schemas, builds the Actor, runs final-build canaries, checks the default and coverage datasets plus `OUTPUT`/`RUN_SUMMARY`, and stops before publication. This repository does not publish the Actor automatically.

# Actor input Schema

## `username` (type: `string`):

Use this when you have one public handle to map across websites. Enter the handle without @, a domain, a URL, email address, or spaces (for example, soxoj). One username is scanned per run for predictable cost and clearer provenance.

## `siteLimit` (type: `integer`):

Set a positive number for a bounded ranked scan (for example, 100), or leave 0 to scan every selected active site in the Maigret catalogue. Defaults to 0. This is a site count, not a result count.

## `siteTags` (type: `array`):

Optionally restrict the scan to Maigret tags such as coding, social, gaming, forum, or us. An empty list keeps all tags. Tags are catalogue labels, not search keywords or profile attributes.

## `excludeTags` (type: `array`):

Optionally exclude Maigret tags from the scan, such as dating or gambling. Adult-oriented tags are excluded automatically unless includeAdultSites is true. These are catalogue filters, not content classifiers.

## `siteNames` (type: `array`):

Optionally check named Maigret sites such as GitHub, Reddit, or VK instead of a broad scan. Leave empty for the ranked/tag-filtered catalogue. Use exact catalogue names when possible; this is not a list of arbitrary URLs.

## `includeAdultSites` (type: `boolean`):

Set true only when adult-oriented public-site coverage is part of an authorized review. Defaults to false and excludes Maigret tags such as nsfw, erotic, adult, and porn. This is a catalogue filter, not a claim about a person.

## `includeDisabledSites` (type: `boolean`):

Set true to force checks for Maigret entries currently marked disabled. The normal scan uses active entries only because disabled definitions can produce false positives or unreliable requests. The coverage dataset records ILLEGAL entries when Maigret skips them.

## `extractProfileData` (type: `boolean`):

Enable Maigret's optional public-page parser for claimed profiles and return bounded scalar profile fields when available. Defaults to false for faster, narrower scans. It does not log in, bypass authentication, or infer identity.

## `updateSiteDatabase` (type: `boolean`):

When true, use Maigret's signed metadata and SHA-256-verified database refresh path, falling back to the pinned package database when offline. Defaults to true. This refreshes site definitions, not search results.

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

Maximum seconds Maigret waits for one site check before returning an uncertain status. Defaults to 5 for full-catalogue throughput; raise it for slow sites at the cost of runtime. This is not the total Actor timeout.

## `concurrency` (type: `integer`):

Maximum concurrent Maigret site checks. Defaults to 100 for the 1 GB profile; lower it when using longer timeouts or a small run memory limit. This is not the number of usernames because this Actor accepts one username per run.

## `retries` (type: `integer`):

Number of Maigret retries for temporary failures. Defaults to 0 so a full scan stays bounded and uncertain sites remain explicitly UNKNOWN. Increase to 1 or 2 when you accept longer runs; this is not a retry for AVAILABLE results.

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

Optional Apify proxy configuration. Residential proxies are the default for public-site reliability; one proxy URL is allocated per run for session consistency. Disable only when you understand the target-site and network tradeoff.

## Actor input object example

```json
{
  "username": "soxoj",
  "siteLimit": 40,
  "siteTags": [],
  "excludeTags": [],
  "siteNames": [],
  "includeAdultSites": false,
  "includeDisabledSites": false,
  "extractProfileData": false,
  "updateSiteDatabase": true,
  "requestTimeoutSecs": 3,
  "concurrency": 40,
  "retries": 0,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `profileMatches` (type: `string`):

Default dataset: claimed public profile rows only. Use the coverage dataset to inspect AVAILABLE, UNKNOWN, and ILLEGAL checks.

## `profileMatchesCsv` (type: `string`):

Default dataset exported as CSV.

## `coverage` (type: `string`):

Named coverage dataset: one row per selected site, including AVAILABLE, UNKNOWN, and ILLEGAL checks. Retrieve through the Storage tab or Dataset API.

## `output` (type: `string`):

Terminal outcome, dataset counts, status counts, charge counts, and warnings.

## `runSummary` (type: `string`):

Full diagnostic contract with database provenance, filters, coverage, persistence, runtime, and charge-limit state.

## `databaseInfo` (type: `string`):

Site database provenance and catalogue counts used by this run.

## `consoleRun` (type: `string`):

Direct link to inspect logs, datasets, and key-value 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 = {
    "username": "soxoj",
    "siteLimit": 40,
    "requestTimeoutSecs": 3,
    "concurrency": 40
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/maigret-username-osint").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 = {
    "username": "soxoj",
    "siteLimit": 40,
    "requestTimeoutSecs": 3,
    "concurrency": 40,
}

# Run the Actor and wait for it to finish
run = client.actor("khadinakbar/maigret-username-osint").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 '{
  "username": "soxoj",
  "siteLimit": 40,
  "requestTimeoutSecs": 3,
  "concurrency": 40
}' |
apify call khadinakbar/maigret-username-osint --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,khadinakbar/maigret-username-osint"
        }
    }
}

```

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/0qLm4eKXEvEhNfsit/builds/6jmTZWrCVEDBV5Cba/openapi.json
