user-scanner

CLI Tool

kaifcodec/user-scanner

Deep email & username OSINT suite with 465+ scan vectors for digital footprinting.

Overview

User Scanner is a Python-based OSINT suite for security research and investigations. It scans 465+ actively maintained platforms to extract metadata, verify account registrations, and pivot across handles and emails. Includes cross-scan engine, proxy rotation, report exports, and MCP server for AI agent integration.

README Preview

# User Scanner\n\n\n  \n\n\n\n  \n  \n  \n  \n  \n  \n  \n     \n  \n\n\n\n  \n    \n  \n\n\n---\n\nA powerful **2-in-1 OSINT suite** engineered for deep **Email and Username Intelligence**.\n\nWith **465+ total scan vectors**—including **175+ email-integrated sites** and **290+ username platforms**—you can map digital footprints, analyze target behavior, uncover interests, full metadata of usernames and verify account registrations in seconds.\n\n---\n\n## 💖 Sponsored by\n\n\n  \n    \n  \n  \n  Go beyond account enumeration. WebVetted turns an email or username into a complete identity investigation with deep OSINT enrichment, breach intel, AI analysis, and an interactive identity graph.\n  \n  Start an Investigation →\n\n\n---\n\n\n  \n    \n  \n  \n  Comprehensive OSINT platform for professional investigators and analysts. Reverse email, phone number, and username search across 250+ modules. Automate your intelligence gathering with our powerful tools.\n  \n  Get Started →\n\n\n---\n\n## ✨ Key Features\n\n- 🔎 **Deep Email & Username OSINT:** Look up email registrations and perform advanced username profiling across 465+ platforms.\n- 👤 **Rich Metadata Scraping:** Scrapes avatars, bio descriptions, follower counts, UID numbers, seller statuses, and account attributes.\n- 🔀 **Cross-Scan & Pivot Engine:** Mines handles, profile links, and exposed email addresses from initial scans, automatically pivoting across secondary target vectors.\n- 🤖 **Model Context Protocol (MCP) Server:** Native AI agent integration for Claude Desktop, Cursor, Antigravity, and LLMs to run autonomous OSINT scans and recursive pivots.\n- 🛡️ **Hudson Rock Infostealer Breach Intel:** Query infostealer malware breach logs using the `--hudson` flag for high-priority target correlation.\n- ⚡ **High-Throughput Parallel Engine:** Powered by `httpx` and `curl_cffi` for maximum concurrency with automated TLS fingerprint impersonation.\n- 🔀 **Permutation & Alias Generator:** Wildcard-based use

FAQ (5)

Troubleshooting
How do I fix broken or incorrect API requests when usernames or emails contain &, #, %, +, spaces, or non-ASCII characters in Python URL query strings?

Do not insert raw user-controlled values directly into an f-string URL. Percent-encode each query value with urllib.parse.quote:

from urllib.parse import quote

url = f"{base_url}{endpoint}?{param}={quote(target, safe='')}"
api_url = f"https://www.instagram.com/api/v1/users/web_profile_info/?username={quote(user, safe='')}"

For multiple parameters, prefer urlencode:

from urllib.parse import urlencode

params = {"username": user, "email": email}
url = f"{base_url}{endpoint}?{urlencode(params)}"

Audit all f-string query URLs, including modules under core/, email_scan/, and user_scan/, and encode every interpolated user, username, email, target, or similar value. Encode only the parameter values, not the full URL. Add regression tests using inputs containing &, #, %, +, whitespace, and non-ASCII characters. The existing leetcode.py usage of urllib.parse.quote() can be used as the reference pattern.

GitHub Issue #574
Troubleshooting
Why does user-scanner hang when concurrency is set to 0 with -C or MCP?

Setting concurrency to 0 creates asyncio.Semaphore(0), so every module waits forever before the per-module timeout starts. In MCP mode, this can also hold the scan lock and block the queue. As a workaround on affected versions (including 1.5.2.1), run scans with a positive concurrency value, such as -C 1, or set MAX_CONCURRENT_REQUESTS=1; do not use 0 or negative values. The fix adds validation in CLI/MCP boundaries and both orchestrator.set_concurrency and email_orchestrator.set_concurrency to raise ValueError for values below 1, with minimum: 1 in the MCP schema. Upgrade to a release containing the fix for early, consistent validation for username and email scans.

GitHub Issue #690
Troubleshooting
How do I fix PDF media downloads bypassing the proxy configured with `-P`/`--proxy-file` in user-scanner?

This is fixed in PR #692. In version 1.5.2.1 (commit 780d077a468035c6afd6b4a0f987317db651528b), pdf_generator.fetch_and_resize_image() calls httpx.get() directly. With httpx 0.28.1, that creates a client with proxy=None, so the configured proxy from get_proxy()/set_proxy_manager() is not used and PDF image requests can reveal the operator's IP.

Upgrade to a release containing PR #692, or apply that patch from source:

git fetch origin pull/692/head:pr-692
git checkout pr-692
python -m pip install -e ".[pdf]"

The patch routes PDF media downloads through get_proxy(), honors get_global_timeout(), and does not silently fall back to a direct connection when the proxy fails. Verify the fix by setting an unreachable proxy such as http://127.0.0.1:1: the media download should fail or be skipped, and the destination server must receive no direct request. If maintaining a fork, replace the direct httpx.get() call in user_scanner/core/pdf_generator.py with the scanner's shared proxied request helper or an explicit client using get_proxy() and get_global_timeout().

GitHub Issue #688
Troubleshooting
How to fix warmup_url only running for the first site in a multi-site user-scanner scan?

This affects user-scanner 1.5.2.1 at commit 780d077a468035c6afd6b4a0f987317db651528b. The _warmed cache is keyed only by (impersonate, proxy), so a successful warmup for one origin marks the shared session as warmed for every other origin, even though clearance cookies are site-specific.

Fix by upgrading to a main-branch version containing PR #680, merged two commits after the affected commit:

python -m pip install -U git+https://github.com/kaifcodec/user-scanner.git@main

If working from a checkout:

git pull origin main
python -m pip install -e .

If you cannot upgrade, cherry-pick/merge PR #680. The correction must scope warmup state by the session/browser plus warmup_url or origin-specific clearance context, not by browser/proxy alone. A failed warmup must remain retryable without clearing other sites' state. As a temporary workaround, run each origin in a separate process so the shared _warmed set is not reused across sites.

Verify by requesting two different origins with the same browser and no proxy: each origin should send its own warmup request once before its normal request, repeated requests should reuse the warmed state, and concurrent/failed warmups should be handled safely.

GitHub Issue #689
Troubleshooting
How do I fix user-scanner Screener returning "Unexpected response body structure" for every email address?

In v1.5.1, screener.in changed its error markup from <ul class="errorlist"> to <ul class="errorlist" id="id_password_error">, so the exact-string check in email_scan/other/screener.py fails. Replace the marker check around line 68 with a regex that tolerates additional attributes:

import re

_REQUIRED = re.compile(r'<ul class="errorlist"[^>]*>\s*<li>This field is required\.</li>')

if _REQUIRED.search(res_text):
    return Result.available(url=show_url)

The previous check was:

if '<ul class="errorlist"><li>This field is required.</li>' in res_text:
    return Result.available(url=show_url)

After patching the installed package file, rerun:

user-scanner -e john.smith.4471@gmail.com -m screener --all

The taken branch is likely unaffected because it matches the plain text User account with this Email already exists. If maintaining the module, also use separate error messages for missing CSRF/token and unclassifiable POST responses to make future markup changes easier to diagnose.

GitHub Issue #611