reconflow
Recon for bug bounty hunters that tells you what changed since your last scan.
pip install reconflow
reconflow chains subfinder and httpx into one command, filters out wildcard DNS noise, saves a snapshot of every run, and lets you diff any two runs to see new subdomains, newly live hosts, and changed responses.
Use responsibly. Only scan domains you own or that are explicitly in scope for a bug bounty / pentest program you are authorized to test.
Features
scan: finds subdomains, drops wildcard DNS false positives (including rotating IP pools), probes live hosts for status code, title and technologies, and writes a Markdown reportdiff: compares your two most recent scans of a domain and highlights what's new- Scan history: every scan saves a structured snapshot, so nothing is overwritten
- Cron-friendly:
diffexits1when something changed and0when nothing did - No Python dependencies beyond the standard library
Requirements
- Python 3.8+
subfinderandhttpx(ProjectDiscovery's Go versions) on yourPATHgowitness(optional, only for--screenshots)
Note:
httpxmust be ProjectDiscovery's tool, not the Pythonhttpxlibrary. On Kali/Debian/Ubuntu it is often packaged ashttpx-toolkit. reconflow checks for both names and verifies the binary.
Check your tools:
subfinder -version
httpx -version
Install
From PyPI:
pip install reconflow
From source:
git clone https://github.com/ErenYeager1836/reconflow.git
cd reconflow
pip install -e .
Usage
reconflow scan example.com
reconflow scan example.com --scope scope.txt
reconflow diff example.com
reconflow scope scope.txt api.example.com notexample.com
You can also run it as a module: python -m reconflow scan example.com
scan
| Option | Description |
|---|---|
domain |
Target domain (required, must be in scope) |
-o, --output |
Output folder (default: output) |
--threads |
Number of threads for probing (default: 10) |
--timeout |
Timeout in seconds for probing (default: 5) |
--keep-wildcard |
Warn about wildcard DNS but don't filter wildcard results |
--json |
Also write structured results to report.json |
--screenshots |
Capture screenshots of live hosts (requires gowitness) |
--scope |
Path to scope file (drops out-of-scope hosts before network activity) |
scope
Verify whether targets are in or out of scope based on a program scope file:
reconflow scope scope.txt api.example.com admin.example.com 192.168.1.10
Scope file format & matching rules
- One entry per line; blank lines and
#comments are ignored. - In-scope entries: exact domains (
example.com), wildcards (*.example.com), and IP/CIDR blocks (192.168.1.0/24). - Out-of-scope entries: prefixed with
!,-, orout:(e.g.!admin.example.com,!10.0.0.0/8). - Out-of-scope entries ALWAYS override in-scope entries.
- Wildcard matching:
*.example.commatches subdomains only (e.g.api.example.com,dev.api.example.com). It does NOT match the apex domainexample.comitself and does NOT matchnotexample.com. The apex domain must be listed explicitly if in scope. - Normalization: Hostnames are normalized first (lowercased; schemes, credentials, ports, paths, and trailing dots are stripped).
- Fail closed: If
--scopeis given and the file is missing, unreadable, empty, or contains no valid in-scope entries, reconflow aborts immediately. Out-of-scope hosts and redirect targets are never probed.
Browser Redirects & Scope:
gowitnesscaptures screenshots in a real headless browser, which automatically follows HTTP redirects.reconflowprotects your scope boundaries by capturing HTTP redirect targets (Locationheaders) viahttpxin all modes and automatically skipping screenshots for any host that redirects to an out-of-scope destination. Note that client-side JavaScript redirects (e.g.window.location) or HTML<meta http-equiv="refresh">redirects execute inside the browser engine and cannot be detected beforehand.
diff
| Option | Description |
|---|---|
domain |
Target domain to compare runs for (required) |
-o, --output |
Output folder (default: output) |
--json |
Print the comparison as JSON |
--notify |
Send webhook alert to Discord or Slack if changes are detected |
--webhook-url |
Webhook URL (or set RECONFLOW_WEBHOOK_URL / DISCORD_WEBHOOK_URL / SLACK_WEBHOOK_URL) |
diff needs at least two saved scans of the same domain. Run scan twice first.
mark
Set triage state for a host on a per-domain basis so reviewed assets stop cluttering differential scans:
# Mark host as reviewed and tested
reconflow mark admin.example.com --tested
# Mark host to be ignored in subsequent diffs
reconflow mark dev-api.example.com --ignore --notes "Mock API for testing"
# List all triaged hosts for a domain
reconflow mark --list -d example.com
| Option | Description |
|---|---|
host |
Hostname or URL to mark |
-d, --domain |
Target domain (inferred if omitted) |
-o, --output |
Output folder (default: output) |
--tested |
Mark host as tested |
--ignore |
Mark host as ignored |
--notes |
Optional notes on the triage decision |
--list |
List all triaged hosts for domain |
Triage Behavior:
--ignore: Permanently silences the host from appearing innew_liveandchangedsections in subsequent diffs.--tested: Hides the host fromnew_liveonce reviewed, but if the host later undergoes a change (e.g. status code changes from 403 to 200, title changes, or new technology is detected), it automatically resurfaces underchangedso you never miss critical updates.
report
Regenerate Markdown (report.md) and JSON (report.json) reports from an existing scan snapshot without re-running any network discovery or probing:
# Regenerate report from the latest scan
reconflow report example.com
# Regenerate report for a specific historical scan run
reconflow report example.com --run 2026-10-18_185218
# Output structured report as JSON
reconflow report example.com --json
| Option | Description |
|---|---|
domain |
Target domain to generate report for (required) |
-o, --output |
Output folder (default: output) |
--run |
Specific scan run ID (defaults to latest scan) |
--json |
Print the regenerated report as JSON |
Track changes with diff
Most recon tools tell you what exists. reconflow also tells you what changed. New subdomains, newly live hosts, and status transitions are annotated with actionable lead hints ("worth checking"):
Example output (illustrative):
[*] Recon diff: 2026-10-18_185218 -> 2026-10-18_190412
============================================================
[+] NEW SUBDOMAINS (2):
+ beta.example.com
+ staging-api.example.com
[+] NEWLY LIVE HOSTS (1):
+ https://beta.example.com [200] [Beta Portal] [Nginx, React]
* Worth checking: Prerelease beta environment; look for unhardened endpoints or debug flags.
[*] CHANGED HOSTS (1):
~ https://admin.example.com
status: 403 -> 200
title: 'Forbidden' -> 'Admin Login'
tech: ['Apache'] -> ['Apache', 'PHP']
* Worth checking: Status changed from 403 to 200; previously protected resource is now publicly accessible.
* Worth checking: Administrative interface; test for panel access, auth bypass, or default credentials.
[-] Removed subdomains (1) [informational]:
- old.example.com
============================================================
Incomplete Scan Safeguards: If a previous or current scan was interrupted (Ctrl+C), missing hosts are never reported as "gone" or removed, and a warning is displayed instead.
Exit codes
| Code | Meaning |
|---|---|
0 |
No changes found (or not enough history to compare) |
1 |
Changes were detected |
Webhook Alerts & Scheduled Automation
Send alerts to Discord or Slack only when new hosts or changes are detected:
# Set webhook in environment (recommended: avoids exposing secrets in shell history or ps)
export RECONFLOW_WEBHOOK_URL="https://discord.com/api/webhooks/..."
# Every 6 hours: rescan, diff, and notify on changes
0 */6 * * * reconflow scan example.com && reconflow diff example.com --notify >> ~/recon-changes.log
Security Note: Using the
RECONFLOW_WEBHOOK_URL(orDISCORD_WEBHOOK_URL/SLACK_WEBHOOK_URL) environment variable is strongly recommended over--webhook-urlto prevent sensitive tokens from appearing in shell history (.bash_history) or process listings (ps aux).
Output
Files are saved under output/<domain>/:
subdomains.txt all discovered subdomains
live.txt live hosts with status code, title, tech
report.md summary report
report.json structured report (with --json)
triage.json triage records (with reconflow mark)
screenshots/ screenshots of live hosts (with --screenshots)
runs/<run_id>/ snapshot of each scan, used by diff
Known limitations
- Wildcard DNS domains return many fake "live" hosts that all point to the same server. reconflow detects them and filters those hosts (use
--keep-wildcardto disable). - Discovery depends on subfinder's sources, so results can vary between runs.
Roadmap
- Subdomain discovery and live host probing
- Wildcard DNS detection (including rotating IP pools)
-
--threadsand--timeoutoptions - JSON report output
- Screenshots of live hosts
- Scan history and
reconflow diff -
reconflow scope: check targets against program scope -
reconflow report: regenerate reports from saved scans - Lead hints in
reconflow diff -
--notify: Discord/Slack webhook alerts for diff results - Triage state:
reconflow mark <host> --tested|--ignore - Save results as they come in
Contributing
Contributions are welcome. Look for issues labelled good first issue. Run the tests with:
python -m unittest discover tests -v
License
MIT
Metadata
Release files for reconflow 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| reconflow-0.3.0.tar.gz | 44.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| reconflow-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 75.4 kB
Release files / reconflow-0.3.0.tar.gz
| Download URL | reconflow-0.3.0.tar.gz |
|---|---|
| Size | 44.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2557ba2dd3e04ec523fec20a2afc98ee5e819ae074eee6472a8d11b38ef1d1bb
|
|
BLAKE2b-256 checksum How to use checksums |
732f41e7f9eb177e069f8758642d442cfb9457344d8cb043976b9f30abc4b72c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.15.0
|
Release files / reconflow-0.3.0-py3-none-any.whl
| Download URL | reconflow-0.3.0-py3-none-any.whl |
|---|---|
| Size | 30.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5d8f5a6fa4dbffcb4d369a54dd5984fbca14ab77ecc9c075934bc018c86785ab
|
|
BLAKE2b-256 checksum How to use checksums |
621b52c4c513d3b867a8dfb3ec788df13c26694a972cabf5c118d4550c19e5d1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.15.0
|