Bulk-IOC-Scanner
Paste a list of indicators — file hashes, IPs, domains, URLs — and get them all checked against threat intelligence sources at once, with a risk score, a history you can search, and reports you can copy straight into a ticket.
It runs on your own machine. Nothing is uploaded except the indicators themselves, and files you scan are hashed locally so only the hash ever leaves your computer.
Install
Pick one of the three. All of them give you the same app at
http://localhost:8000.
| Option | Best for | Needs |
|---|---|---|
| Download and run | The quickest start, no tools to install | Nothing |
| pipx / uvx | Keeping it updated, macOS users | Python 3.11+ |
| Docker | Servers, shared team instances | Docker |
Option 1: Download and run
Grab the file for your system from the latest release.
Windows — download bulk-ioc-scanner-windows-x64.exe and double-click it.
Windows will warn you the app is unrecognised, because the file is not code signed. Click More info, then Run anyway.
Linux — download bulk-ioc-scanner-linux-x64, then:
chmod +x bulk-ioc-scanner-linux-x64
./bulk-ioc-scanner-linux-x64
macOS — there is no prebuilt Mac app; use pipx or Docker instead.
Option 2: Install with pipx or uvx
Needs Python 3.11 or newer.
pipx install bulk-ioc-scanner
bulk-ioc-scanner
Or run it without installing anything permanently:
uvx bulk-ioc-scanner
Getting pipx
| System | Command |
|---|---|
| Windows | py -m pip install --user pipx then py -m pipx ensurepath |
| macOS | brew install pipx then pipx ensurepath |
| Debian / Ubuntu / Kali | sudo apt install pipx then pipx ensurepath |
| Fedora | sudo dnf install pipx then pipx ensurepath |
Close and reopen your terminal after ensurepath.
To update later: pipx upgrade bulk-ioc-scanner
Option 3: Docker
docker run -d --name bulk-ioc-scanner \
-p 8000:8000 \
-v bulk-ioc-scanner-data:/data \
ghcr.io/hashemsalhi/bulk-ioc-scanner:latest
Then open http://localhost:8000. Your history and keys live in the
bulk-ioc-scanner-data volume and survive upgrades.
Or, from a copy of this repository, docker compose up -d.
First run
- Start it. A browser tab opens at
http://localhost:8000on its own. - Go to Scan, paste your indicators — one per line, or comma separated — and press Scan.
- Results appear as they arrive. Click any row for the full per-source breakdown, tag it, add notes, or copy a formatted report.
Defanged indicators are fine: 8[.]8[.]8[.]8 and hxxps://evil[.]com are
understood and cleaned up automatically.
You can also drop files in. They are hashed on your machine and only the SHA-256 is sent out — the file contents never leave.
About API keys
You do not need any API key to start. RDAP/WHOIS works immediately and covers IPs, domains, and network ownership.
For hashes and URLs you will want at least one key. They are free, take about a minute, and go in the Settings page inside the app — there is no config file to edit.
| Source | What it adds | Free key |
|---|---|---|
| RDAP / WHOIS | Registrar, domain age, network owner | Not needed |
| VirusTotal | Multi-vendor verdicts for hashes, IPs, domains, URLs | virustotal.com |
| AbuseIPDB | IP abuse reports and confidence score | abuseipdb.com |
| GreyNoise | Tells internet background noise from targeted activity | greynoise.io |
| ThreatFox | Known malware indicators from abuse.ch | auth.abuse.ch |
| URLScan.io | Existing scans and screenshots of a URL | urlscan.io |
| IPify | Geolocation and ASN for an IP | geo.ipify.org |
Any source without a key is skipped. You can switch individual sources on and off on the Settings page.
Where your data is kept
Scan history and API keys go in one folder, outside the program itself, so upgrading or reinstalling never loses them:
| System | Folder |
|---|---|
| Windows | %LOCALAPPDATA%\BulkIOCScanner |
| macOS | ~/Library/Application Support/BulkIOCScanner |
| Linux | ~/.local/share/bulk-ioc-scanner |
| Docker | the /data volume |
To back up, copy bulk_ioc_scanner.db out of that folder. To start
clean, delete it. To keep it somewhere else, start with
bulk-ioc-scanner --data-dir "D:\cases\ioc-data".
The database contains your API keys in plain text and is created readable only by your user account. Treat a copy of it the way you would treat the keys.
On a corporate network
If your organisation routes traffic through a proxy or inspects TLS, scans will
fail until it is told how to get out. Everything below can go in a .env file
in your data folder, or be set as environment variables.
Behind a proxy — the standard variables are picked up automatically:
HTTPS_PROXY=http://proxy.example.corp:8080
NO_PROXY=localhost,127.0.0.1
To force one regardless of the environment, set PROXY_URL instead.
TLS inspection — if your company issues its own certificates, point the app at the CA bundle:
CA_BUNDLE=/path/to/corporate-ca.pem
If you already have REQUESTS_CA_BUNDLE, SSL_CERT_FILE, or CURL_CA_BUNDLE
set for curl or pip, those are used automatically and you need to do nothing.
Slow links — raise the timeouts:
REQUEST_TIMEOUT_SECONDS=60
CONNECT_TIMEOUT_SECONDS=20
Rate limits are handled for you: a source that answers "too many requests" is retried with a growing delay and then paced more slowly, and a source that is down or blocked only costs you its own column — the rest of the scan finishes normally.
As a last resort you can set
INSECURE_SKIP_VERIFY=trueto stop checking certificates. PreferCA_BUNDLE; skipping verification means you cannot tell your proxy from an attacker.
Troubleshooting
| Problem | Fix |
|---|---|
| Windows: "Windows protected your PC" | Click More info → Run anyway. The file is unsigned, not malicious. |
| The browser did not open | Go to http://localhost:8000 yourself. The address is printed in the terminal. |
| "Port 8000 is in use" | Nothing to do — it moves to the next free port and tells you which. Or pick one: --port 9000. |
| Linux: "cannot execute binary file" | Run chmod +x bulk-ioc-scanner-linux-x64 first. |
| Linux: a GLIBC version error | Your distribution is older than the build. Use pipx or Docker instead. |
pipx: command not found |
Run pipx ensurepath, then close and reopen your terminal. |
| Every scan fails with a connection error | You are probably behind a proxy — see On a corporate network. |
| "certificate verify failed" | TLS inspection. Set CA_BUNDLE to your organisation's certificate. |
| A hash comes back "no active provider" | Only RDAP is on, and it does not do hashes. Add a VirusTotal key on the Settings page. |
| "invalid API key" | Re-paste the key on the Settings page; keys are easy to truncate when copying. |
| Scans are slow | Free tiers are rate limited — VirusTotal allows 4 lookups a minute. Repeat scans of the same indicator are served from a 24-hour cache. |
| The page is blank | Hard-refresh with Ctrl+Shift+R (Cmd+Shift+R on a Mac). |
Still stuck? Open an issue with what you ran and what you saw.
Options
bulk-ioc-scanner [--host HOST] [--port PORT] [--no-browser]
[--data-dir PATH] [--log-level LEVEL] [--version]
--host 0.0.0.0 makes it reachable from other machines. There is no login
screen, so only do that on a network you trust.
Uninstall
| Installed with | Remove the app | Remove your data |
|---|---|---|
| Download | Delete the downloaded file | Delete the data folder |
| pipx | pipx uninstall bulk-ioc-scanner |
Delete the data folder |
| Docker | docker rm -f bulk-ioc-scanner |
docker volume rm bulk-ioc-scanner-data |
Contributing
Working on the code is covered in DEVELOPMENT.md.
License
MIT.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file bulk_ioc_scanner-1.0.0.tar.gz.
File metadata
- Download URL: bulk_ioc_scanner-1.0.0.tar.gz
- Upload date:
- Size: 85.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ec4125a01c8d296c4fd1c7f74c902097727503f329e2116c2149d98d5a379ad5
|
|
| MD5 |
62f3e156080d23e1e602ce355d0b59cd
|
|
| BLAKE2b-256 |
9ccf77d71f793db74c3e42e91e6e786b456803174c8a5f274b8feaf0eb199aa8
|
Provenance
The following attestation bundles were made for bulk_ioc_scanner-1.0.0.tar.gz:
Publisher:
release.yml on HashemSalhi/Bulk-IOC-Scanner
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bulk_ioc_scanner-1.0.0.tar.gz -
Subject digest:
ec4125a01c8d296c4fd1c7f74c902097727503f329e2116c2149d98d5a379ad5 - Sigstore transparency entry: 2441283488
- Sigstore integration time:
-
Permalink:
HashemSalhi/Bulk-IOC-Scanner@5d095cb945f2c754a7b7404f21fd3103c72c3d8e -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/HashemSalhi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5d095cb945f2c754a7b7404f21fd3103c72c3d8e -
Trigger Event:
push
-
Statement type:
File details
Details for the file bulk_ioc_scanner-1.0.0-py3-none-any.whl.
File metadata
- Download URL: bulk_ioc_scanner-1.0.0-py3-none-any.whl
- Upload date:
- Size: 54.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b329766da12159be96d26439dd51bd7e5ebaf7d825614bead19d768b2b5b6b51
|
|
| MD5 |
447952fcf58e174dc2dddae2ab69a6c3
|
|
| BLAKE2b-256 |
c91347d9a6773934d066766d8aa2c38767d08694922f9a4b238f9397aa0eb258
|
Provenance
The following attestation bundles were made for bulk_ioc_scanner-1.0.0-py3-none-any.whl:
Publisher:
release.yml on HashemSalhi/Bulk-IOC-Scanner
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bulk_ioc_scanner-1.0.0-py3-none-any.whl -
Subject digest:
b329766da12159be96d26439dd51bd7e5ebaf7d825614bead19d768b2b5b6b51 - Sigstore transparency entry: 2441283954
- Sigstore integration time:
-
Permalink:
HashemSalhi/Bulk-IOC-Scanner@5d095cb945f2c754a7b7404f21fd3103c72c3d8e -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/HashemSalhi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5d095cb945f2c754a7b7404f21fd3103c72c3d8e -
Trigger Event:
push
-
Statement type: