Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

spyglass-lite

OSINT recon you can import. Username enumeration, email intelligence, IP, ASN and phone lookups — no external binaries, no API keys, no CLI.

CI Status Release License Python

Quick Start · Docs · Report Bug · Request Feature


Why spyglass-lite?

  • Importable: Stop shelling out to subprocesses. Integrate recon directly into your Python apps.
  • Precision First: Unlike other tools, lite employs a rigorous verification layer to eliminate false positives from bot walls and generic landing pages.
  • Offline & Safe: No external binary dependencies. No OS-level CLI installations required.
  • Transparent: Results are clearly categorized into found, absent, and unknown (with reasons).

Table of Contents


Quick Start

import spyglass_lite as sg

# Quick check: stop after 20 seconds, keep whatever was decided by then
result = sg.username("johndoe", deadline=20)
for profile in result.found:
    print(f"Found on {profile.platform}: {profile.url} ({profile.confidence})")

A full scan of all 2,285 sites takes a couple of minutes. For a first look, pass deadline=; for a narrower look, pass sites=. Both return real results, not an error:

result = sg.username("johndoe", sites=["github.com", "x.com", "reddit.com"])
print(result)          # <UsernameResult 'johndoe': 2 found, 1 unknown>
print(result.partial)  # True if a deadline cut the scan short

Fewer hits than expected? Read result.unknown. A site that blocks bots (403), shows a challenge page, or serves the same shell to every handle is reported there with the reason — it is not silently counted as "no account". unknown is the honest middle state, and it is usually the bigger list. A site that is merely slow shows up as a request failed (…Timeout…): the default per-request timeout is 10 seconds, and it is better to bound the scan with deadline= than to shorten every request — a 6s timeout was measured to save no wall-clock time on a full scan while losing slow-but-real profiles.


Architecture

spyglass-lite is the importable core of Spyglass OSINT, rewritten for in-process execution. It avoids the orchestration of external CLI tools (Sherlock, Maigret, etc.) by embedding the site rules and engines directly, ensuring consistent results and removing environmental fragility.


Features

Module Returns Needs
username() Platforms where a handle exists 2,285 bundled site rules
email() Validation, MX/provider, SPF/DMARC, Gravatar, breach hits HTTP + DNS
ip() Geolocation, reverse DNS, WHOIS, passive ports HTTP + WHOIS/43
asn() Covering prefix, origin AS, RPKI state RIPEStat
phone() Carrier, region, line type, formats [phone] extra

Installation

pip install spyglass-lite
pip install "spyglass-lite[phone]"    # optional: phonenumbers

Python 3.11+. Core dependencies: httpx and dnspython>=2.9.0.


Configuration

import spyglass_lite as sg

# Configure a custom client
client = sg.lite(
    timeout=8,          # per request, seconds (default 10)
    concurrency=100,    # global in-flight cap (default 50)
    per_host=2,         # cap per hostname
    retries=1,          # transient HTTP statuses only
    proxy="socks5://127.0.0.1:9050",   # needs spyglass-lite[socks]
)

# Use your custom client
client.username("johndoe", limit=500)

Usage

Username Enumeration

# Stop after 30 seconds; take what has been decided by then
r = sg.username("johndoe", deadline=30)
if r.partial:
    print("the clock cut the scan short")

# Specific sites only — display names, domains, or full URLs
r = sg.username("johndoe", sites=["github.com", "https://x.com/someone"])

# A full scan of every bundled site (no deadline). ``limit`` keeps the N most
# popular sites, which are often the bot-walled ones — pair it with deadline=
# rather than expecting it to be quick.
r = sg.username("johndoe", limit=300, deadline=20)

# Raw mode: the dataset rule only, no verification layer and no
# catch-all probe. Used to compare against Sherlock/Maigret output.
r = sg.username("johndoe", judge=False)

# High-confidence results only
for profile in r.high_confidence:
    print(profile.url)

# Audit unknown results — this is why the found list is short
for u in r.unknown:
    print(f"{u.domain} could not be decided: {u.reason}")

By default every hit passes the verification layer: challenge and registration pages, empty app shells, search/listing URLs, and sites that serve the same page for any handle are reported as unknown with the reason, not as accounts.

Email Intelligence

Tier A (passive) is default. Tier B (active account existence) is opt-in:

sg.email("me@example.com", registrations=True, recipes_path="my-recipes.json")

# Or pass recipes inline / pick bundled ones by domain — see docs/RECIPES.md
sg.email("me@example.com", sites=[{"name": "Example", "url": "https://…", "exists_when": {...}}])

Two things a caller should know before using email():

  • It talks to third parties about the address. Gravatar receives the MD5 hash (and the plain address during a profile lookup), and the two breach APIs receive the address itself. Use gravatar=False, breaches=False to keep the lookup local to DNS.
  • sites= fetches the URLs you give it. Literal private, loopback and link-local hosts (127.0.0.1, 169.254.169.254, [::1], *.internal) are refused, so it is not a naive SSRF primitive — but a hostname that resolves privately, or a public URL that redirects to one, is still reachable. Do not pass untrusted recipe URLs to a service you expose.

Testing

python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev,phone]"

pytest -q                 # offline: every HTTP and DNS call is mocked
ruff check src tests bench scripts
ruff format --check src tests bench scripts
mypy
python -m build

Repository Structure

.
├── bench/                # Benchmarking harness vs Sherlock/Maigret
├── docs/                 # Documentation (RECIPES.md, AUDIT.md)
├── scripts/              # Dataset generation + maintainer comparison tools
├── src/spyglass_lite/    # Core package source
└── tests/                # 219 mocked offline tests

Contributing

  1. Fork the repository.
  2. Create a feature branch.
  3. Run pytest and ruff.
  4. Submit a Pull Request.

License

MIT. Derived from Spyglass OSINT (MIT, © Atheer), and includes site rules from Sherlock (MIT) and Maigret (MIT). See NOTICE.

Metadata

Release files for spyglass-lite 0.9.0b0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for spyglass-lite 0.9.0b0
File Size Uploaded Provenance Actions
spyglass_lite-0.9.0b0.tar.gz 210.4 kB Without provenance Details for spyglass_lite-0.9.0b0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for spyglass-lite 0.9.0b0
File Interpreter ABI Platform Actions
spyglass_lite-0.9.0b0-py3-none-any.whl Python 3 none any Details for spyglass_lite-0.9.0b0-py3-none-any.whl

Total release size: 375.1 kB

Release files / spyglass_lite-0.9.0b0.tar.gz

Download URL spyglass_lite-0.9.0b0.tar.gz
Size 210.4 kB
Tags Source
SHA-256 checksum
How to use checksums
f84d8b7b717241a1fea5ac9fef3310e71aee7c55807d105a99d3dfcc55ff300a
BLAKE2b-256 checksum
How to use checksums
e2b4add418c242df57e03d1061d853a30f9edbe11ce335ca6fc195598fac5867
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.15

Release files / spyglass_lite-0.9.0b0-py3-none-any.whl

Download URL spyglass_lite-0.9.0b0-py3-none-any.whl
Size 164.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7b15bc51c038d3d21cdc468c0334d13cac38a7459208a04176b0644b9cd3af38
BLAKE2b-256 checksum
How to use checksums
e024baabcbda8724d2fba0f8890df50632de5221d7670906dde397560c5c5867
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.15

Security for spyglass-lite 0.9.0b0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page