> ## Documentation Index
> Fetch the complete documentation index at: https://docs.osintcat.net/llms.txt
> Use this file to discover all available pages before exploring further.

# Username Footprint

> Discover platform registrations for a username across 100+ services

The Username Footprint API checks whether a given username is registered across social media, gaming, and community platforms.
It returns a summary and a per-platform breakdown including secondary metadata like profile IDs or account status where available.

The lookup backend is load-balanced, so footprint scans run as **asynchronous tasks**:

1. **Create a task** with `GET /api/footprint/create-task` (this is where one lookup is charged). You receive a `task_id`.
2. **Poll the task** with `GET /api/footprint/get-task?id=<task_id>` until `status` is no longer a running state. Polling is free.

<Note>
  Username and email footprints share the same task endpoints — only the `type` parameter differs (`username` vs `email`).
</Note>

***

## Step 1 — Create Task

```bash theme={null}
GET https://www.osintcat.net/api/footprint/create-task
```

<ParamField query="query" type="string" required>
  The username to scan (e.g., `johndoe`)
</ParamField>

<ParamField query="type" type="string" default="email" required>
  The footprint type. Use `username` for this endpoint.
</ParamField>

<ParamField header="X-API-KEY" type="string" required>
  Your API key
</ParamField>

<Warning>
  Creating a task consumes exactly **one lookup** from your daily quota. Polling `get-task` does not.
</Warning>

**Response Body**

<ResponseField name="task_id" type="string">
  The identifier used to poll for results.
</ResponseField>

<ResponseField name="status" type="string">
  The initial task status (e.g., `running`, `queued`, `pending`).
</ResponseField>

<ResponseField name="_meta" type="object">
  <Expandable title="properties">
    <ResponseField name="plan" type="string">Your current plan.</ResponseField>
    <ResponseField name="lookups_left" type="string">Remaining lookups for the day (`unlimited` on the Max plan).</ResponseField>
  </Expandable>
</ResponseField>

```json theme={null}
{
  "task_id": "f3c8a1e2-9b44-4d51-bd0a-1c2e3f4a5b6c",
  "status": "running",
  "_meta": {
    "plan": "researcher",
    "lookups_left": 4821
  }
}
```

***

## Step 2 — Poll Task

```bash theme={null}
GET https://www.osintcat.net/api/footprint/get-task
```

<ParamField query="id" type="string" required>
  The `task_id` returned by `create-task`.
</ParamField>

<ParamField header="X-API-KEY" type="string" required>
  Your API key
</ParamField>

Poll roughly once per second until `status` is no longer one of the running states
(`running`, `queued`, `pending`, `processing`, `started`). A scan typically completes
within a few seconds and is capped at \~3 minutes.

**Response Body**

<ResponseField name="status" type="string">
  Current task status. While running it is one of `running`, `queued`, `pending`,
  `processing`, `started`. Any other value (e.g., `done`, `finished`) means the scan is complete.
</ResponseField>

<ResponseField name="stats" type="object">
  Live progress / summary counters (populated as the scan runs).

  <Expandable title="properties">
    <ResponseField name="checked" type="number">Number of platforms checked so far.</ResponseField>
    <ResponseField name="total_modules" type="number">Total number of platforms in the scan.</ResponseField>
    <ResponseField name="found" type="number">Number of platforms where the username was found.</ResponseField>
    <ResponseField name="elapsed" type="string">Elapsed scan time.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="results" type="array">
  List of platform results (grows as the scan progresses).

  <Expandable title="item properties">
    <ResponseField name="domain" type="string">Platform domain (e.g., `github.com`)</ResponseField>
    <ResponseField name="taken" type="boolean">True if the username is registered on this platform</ResponseField>

    <ResponseField name="ExtraData" type="object">
      Metadata retrieved from the platform (profile IDs, avatar URLs, follower counts, etc.)
    </ResponseField>
  </Expandable>
</ResponseField>

***

## Example

<CodeGroup>
  ```bash cURL theme={null}
  # 1. Create the task
  curl "https://www.osintcat.net/api/footprint/create-task?query=johndoe&type=username" \
       -H "X-API-KEY: YOUR_API_KEY"

  # 2. Poll until done (replace TASK_ID with the returned task_id)
  curl "https://www.osintcat.net/api/footprint/get-task?id=TASK_ID" \
       -H "X-API-KEY: YOUR_API_KEY"
  ```

  ```python Python theme={null}
  import time
  import requests

  BASE = "https://www.osintcat.net"
  HEADERS = {"X-API-KEY": "YOUR_API_KEY"}
  RUNNING = {"running", "queued", "pending", "processing", "started"}

  # 1. Create the task (charges one lookup)
  task = requests.get(
      f"{BASE}/api/footprint/create-task",
      params={"query": "johndoe", "type": "username"},
      headers=HEADERS,
  ).json()
  task_id = task["task_id"]

  # 2. Poll until the scan finishes
  while True:
      data = requests.get(
          f"{BASE}/api/footprint/get-task",
          params={"id": task_id},
          headers=HEADERS,
      ).json()
      if str(data.get("status", "")).lower() not in RUNNING:
          break
      time.sleep(1)

  print(data)
  ```

  ```javascript Node.js theme={null}
  const BASE = 'https://www.osintcat.net';
  const HEADERS = { 'X-API-KEY': 'YOUR_API_KEY' };
  const RUNNING = ['running', 'queued', 'pending', 'processing', 'started'];
  const sleep = ms => new Promise(r => setTimeout(r, ms));

  (async () => {
    // 1. Create the task (charges one lookup)
    const task = await fetch(
      `${BASE}/api/footprint/create-task?query=johndoe&type=username`,
      { headers: HEADERS }
    ).then(r => r.json());

    // 2. Poll until the scan finishes
    let data;
    do {
      data = await fetch(
        `${BASE}/api/footprint/get-task?id=${encodeURIComponent(task.task_id)}`,
        { headers: HEADERS }
      ).then(r => r.json());
      if (!RUNNING.includes(String(data.status).toLowerCase())) break;
      await sleep(1000);
    } while (true);

    console.log(data);
  })();
  ```

  ```php PHP theme={null}
  <?php

  $base = "https://www.osintcat.net";
  $headers = ["X-API-KEY: YOUR_API_KEY"];
  $running = ["running", "queued", "pending", "processing", "started"];

  function get_json($url, $headers) {
      $curl = curl_init();
      curl_setopt_array($curl, [
          CURLOPT_URL => $url,
          CURLOPT_RETURNTRANSFER => true,
          CURLOPT_HTTPHEADER => $headers,
      ]);
      $response = curl_exec($curl);
      curl_close($curl);
      return json_decode($response, true);
  }

  // 1. Create the task (charges one lookup)
  $task = get_json("$base/api/footprint/create-task?query=johndoe&type=username", $headers);
  $taskId = $task["task_id"];

  // 2. Poll until the scan finishes
  do {
      $data = get_json("$base/api/footprint/get-task?id=" . urlencode($taskId), $headers);
      if (!in_array(strtolower($data["status"]), $running)) break;
      sleep(1);
  } while (true);

  print_r($data);
  ```

  ```go Go theme={null}
  package main

  import (
      "encoding/json"
      "fmt"
      "io"
      "net/http"
      "net/url"
      "strings"
      "time"
  )

  func getJSON(u string) map[string]interface{} {
      req, _ := http.NewRequest("GET", u, nil)
      req.Header.Set("X-API-KEY", "YOUR_API_KEY")
      resp, _ := http.DefaultClient.Do(req)
      defer resp.Body.Close()
      body, _ := io.ReadAll(resp.Body)
      var out map[string]interface{}
      json.Unmarshal(body, &out)
      return out
  }

  func main() {
      base := "https://www.osintcat.net"
      running := map[string]bool{"running": true, "queued": true, "pending": true, "processing": true, "started": true}

      // 1. Create the task (charges one lookup)
      params := url.Values{}
      params.Add("query", "johndoe")
      params.Add("type", "username")
      task := getJSON(base + "/api/footprint/create-task?" + params.Encode())
      taskID, _ := task["task_id"].(string)

      // 2. Poll until the scan finishes
      var data map[string]interface{}
      for {
          data = getJSON(base + "/api/footprint/get-task?id=" + url.QueryEscape(taskID))
          status, _ := data["status"].(string)
          if !running[strings.ToLower(status)] {
              break
          }
          time.Sleep(time.Second)
      }
      fmt.Printf("%+v\n", data)
  }
  ```
</CodeGroup>

**Example Result (completed task)**

```json theme={null}
{
  "status": "done",
  "stats": {
    "checked": 112,
    "total_modules": 112,
    "found": 34,
    "elapsed": "5.1s"
  },
  "results": [
    {
      "domain": "github.com",
      "taken": true,
      "ExtraData": {
        "ProfileURL": "https://github.com/johndoe",
        "PublicRepos": 17
      }
    },
    {
      "domain": "reddit.com",
      "taken": false,
      "ExtraData": {}
    }
  ]
}
```
