Skip to content

Scanning Overview

Scan Names

Every BBOT scan gets a random, mildly-entertaining name like demonic_jimmy. Output for that scan, including scan stats and any web screenshots, are saved to a folder by that name in ~/.bbot/scans. The most recent 20 scans are kept, and older ones are removed.

If you don't want a random name, you can change it with -n. You can also change the location of BBOT's output with -o:

# save everything to the folder "my_scan" in the current directory
bbot -t -f subdomain-enum -m gowitness -n my_scan -o .

If you reuse a scan name, BBOT will automatically append to your previous output files.

Targets (-t)

Targets declare what's in-scope, and seed a scan with initial data. BBOT accepts an unlimited number of targets. They can be any of the following:

  • DNS_NAME (
  • IP_RANGE (
  • URL (

Note that BBOT only discriminates down to the host level. This means, for example, if you specify a URL as the target, the scan will be seeded with that URL, but the scope of the scan will be the entire host, Other ports/URLs on that same host may also be scanned.

You can specify targets directly on the command line, load them from files, or both! For example:

$ cat targets.txt

# load targets from a file and from the command-line
$ bbot -t targets.txt -m nmap

On start, BBOT automatically converts Targets into Events.

Modules (-m)

To see a full list of modules and their descriptions, use bbot -l or see List of Modules.

Modules are the part of BBOT that does the work -- port scanning, subdomain brute-forcing, API querying, etc. Modules consume Events (IP_ADDRESS, DNS_NAME, etc.) from each other, process the data in a useful way, then emit the results as new events. You can enable individual modules with -m.

# Enable modules: nmap, sslcert, and httpx
bbot -t -m nmap sslcert httpx

Types of Modules

Modules fall into three categories:

  • Scan Modules:
    • These make up the majority of modules. Examples are nmap, sslcert, httpx, etc. Enable with -m.
  • Output Modules:
    • These output scan data to different formats/destinations. human, json, and csv are enabled by default. Enable others with -om. (See: Output)
  • Internal Modules:
    • These modules perform essential, common-sense tasks. They are always enabled, unless explicitly disabled via the config (e.g. -c speculate=false).
      • aggregate: Summarizes results at the end of a scan
      • excavate: Extracts useful data such as subdomains from webpages, etc.
      • speculate: Intelligently infers new events, e.g. OPEN_TCP_PORT from URL or IP_ADDRESS from IP_NETWORK.

For details in the inner workings of modules, see Creating a Module.

Flags (-f)

Flags are how BBOT categorizes its modules. In a way, you can think of them as groups. Flags let you enable a bunch of similar modules at the same time without having to specify them each individually. For example, -f subdomain-enum would enable every module with the subdomain-enum flag.

# list all subdomain-enum modules
bbot -f subdomain-enum -l

Filtering Modules

Modules can be easily enabled/disabled based on their flags:

  • -f Enable these flags (e.g. -f subdomain-enum)
  • -rf Require modules to have this flag (e.g. -rf safe)
  • -ef Exclude these flags (e.g. -ef slow)
  • -em Exclude these individual modules (e.g. -em ipneighbor)
  • -lf List all available flags

Every module is either safe or aggressive, and either active or passive. These can be useful for filtering. For example, if you wanted to enable all the safe modules, but exclude active ones, you could do:

# Enable safe modules but exclude active ones
bbot -t -f safe -ef active

This is equivalent to requiring the passive flag:

# Enable safe modules but only if they're also passive
bbot -t -f safe -rf passive

A single module can have multiple flags. For example, the securitytrails module is passive, safe, subdomain-enum. Below is a full list of flags and their associated modules.

List of Flags

Flag # Modules Description Modules
safe 82 Non-intrusive, safe to run affiliates, aggregate, ajaxpro, anubisdb, asn, azure_realm, azure_tenant, baddns, baddns_zone, badsecrets, bevigil, binaryedge, bucket_amazon, bucket_azure, bucket_digitalocean, bucket_file_enum, bucket_firebase, bucket_google, builtwith, c99, censys, certspotter, chaos, code_repository, columbus, credshed, crobat, crt, dehashed, digitorus, dnscommonsrv, dnsdumpster, docker_pull, dockerhub, emailformat, filedownload, fingerprintx, fullhunt, git, git_clone, github_codesearch, github_org, github_workflows, gitlab, gowitness, hackertarget, httpx, hunt, hunterio, iis_shortnames, internetdb, ip2location, ipstack, leakix, myssl, newsletters, ntlm, oauth, otx, passivetotal, pgp, postman, rapiddns, riddler, robots, secretsdb, securitytrails, shodan_dns, sitedossier, skymem, social, sslcert, subdomaincenter, sublist3r, threatminer, trufflehog, urlscan, viewdns, virustotal, wappalyzer, wayback, zoomeye
passive 62 Never connects to target systems affiliates, aggregate, anubisdb, asn, azure_realm, azure_tenant, bevigil, binaryedge, bucket_file_enum, builtwith, c99, censys, certspotter, chaos, code_repository, columbus, credshed, crobat, crt, dehashed, digitorus, dnscommonsrv, dnsdumpster, docker_pull, dockerhub, emailformat, excavate, fullhunt, git_clone, github_codesearch, github_org, github_workflows, hackertarget, hunterio, internetdb, ip2location, ipneighbor, ipstack, leakix, massdns, myssl, otx, passivetotal, pgp, postman, rapiddns, riddler, securitytrails, shodan_dns, sitedossier, skymem, social, speculate, subdomaincenter, sublist3r, threatminer, trufflehog, urlscan, viewdns, virustotal, wayback, zoomeye
subdomain-enum 45 Enumerates subdomains anubisdb, asn, azure_realm, azure_tenant, baddns_zone, bevigil, binaryedge, builtwith, c99, censys, certspotter, chaos, columbus, crt, digitorus, dnscommonsrv, dnsdumpster, fullhunt, github_codesearch, github_org, hackertarget, httpx, hunterio, internetdb, ipneighbor, leakix, massdns, myssl, oauth, otx, passivetotal, postman, rapiddns, riddler, securitytrails, shodan_dns, sitedossier, sslcert, subdomaincenter, subdomains, threatminer, urlscan, virustotal, wayback, zoomeye
active 42 Makes active connections to target systems ajaxpro, baddns, baddns_zone, badsecrets, bucket_amazon, bucket_azure, bucket_digitalocean, bucket_firebase, bucket_google, bypass403, dastardly, dotnetnuke, ffuf, ffuf_shortnames, filedownload, fingerprintx, generic_ssrf, git, gitlab, gowitness, host_header, httpx, hunt, iis_shortnames, masscan, newsletters, nmap, ntlm, nuclei, oauth, paramminer_cookies, paramminer_getparams, paramminer_headers, robots, secretsdb, smuggler, sslcert, telerik, url_manipulation, vhost, wafw00f, wappalyzer
web-thorough 29 More advanced web scanning functionality ajaxpro, azure_realm, badsecrets, bucket_amazon, bucket_azure, bucket_digitalocean, bucket_firebase, bucket_google, bypass403, dastardly, dotnetnuke, ffuf_shortnames, filedownload, generic_ssrf, git, host_header, httpx, hunt, iis_shortnames, nmap, ntlm, oauth, robots, secretsdb, smuggler, sslcert, telerik, url_manipulation, wappalyzer
aggressive 20 Generates a large amount of network traffic bypass403, dastardly, dotnetnuke, ffuf, ffuf_shortnames, generic_ssrf, host_header, ipneighbor, masscan, massdns, nmap, nuclei, paramminer_cookies, paramminer_getparams, paramminer_headers, smuggler, telerik, url_manipulation, vhost, wafw00f
web-basic 17 Basic, non-intrusive web scan functionality azure_realm, baddns, badsecrets, bucket_amazon, bucket_azure, bucket_firebase, bucket_google, filedownload, git, httpx, iis_shortnames, ntlm, oauth, robots, secretsdb, sslcert, wappalyzer
cloud-enum 12 Enumerates cloud resources azure_realm, azure_tenant, baddns, baddns_zone, bucket_amazon, bucket_azure, bucket_digitalocean, bucket_file_enum, bucket_firebase, bucket_google, httpx, oauth
slow 10 May take a long time to complete bucket_digitalocean, dastardly, docker_pull, fingerprintx, git_clone, paramminer_cookies, paramminer_getparams, paramminer_headers, smuggler, vhost
affiliates 8 Discovers affiliated hostnames/domains affiliates, azure_realm, azure_tenant, builtwith, oauth, sslcert, viewdns, zoomeye
email-enum 7 Enumerates email addresses dehashed, emailformat, emails, hunterio, pgp, skymem, sslcert
deadly 4 Highly aggressive dastardly, ffuf, nuclei, vhost
portscan 3 Discovers open ports internetdb, masscan, nmap
web-paramminer 3 Discovers HTTP parameters through brute-force paramminer_cookies, paramminer_getparams, paramminer_headers
baddns 2 Runs all modules from the DNS auditing tool BadDNS baddns, baddns_zone
iis-shortnames 2 Scans for IIS Shortname vulnerability ffuf_shortnames, iis_shortnames
report 2 Generates a report at the end of the scan affiliates, asn
social-enum 2 Enumerates social media httpx, social
repo-enum 1 Enumerates code repositories code_repository
service-enum 1 Identifies protocols running on open ports fingerprintx
subdomain-hijack 1 Detects hijackable subdomains baddns
web-screenshots 1 Takes screenshots of web pages gowitness


BBOT modules have external dependencies ranging from OS packages (openssl) to binaries (nmap) to Python libraries (wappalyzer). When a module is enabled, installation of its dependencies happens at runtime with Ansible. BBOT provides several command-line flags to control how dependencies are installed.

  • --no-deps - Don't install module dependencies
  • --force-deps - Force install all module dependencies
  • --retry-deps - Try again to install failed module dependencies
  • --ignore-failed-deps - Run modules even if they have failed dependencies
  • --install-all-deps - Install dependencies for all modules (useful if you are provisioning a pentest system and want to install everything ahead of time)

For details on how Ansible playbooks are attached to BBOT modules, see How to Write a Module.


For pentesters and bug bounty hunters, staying in scope is extremely important. BBOT takes this seriously, meaning that active modules (e.g. nuclei) will only touch in-scope resources.

By default, scope is whatever you specify with -t. This includes child subdomains. For example, if you specify -t, all its subdomains (,, etc.) also become in-scope.

Scope Distance

Since BBOT is recursive, it would quickly resort to scanning the entire internet without some kind of restraining mechanism. To solve this problem, every event discovered by BBOT is assigned a Scope Distance. Scope distance represents how far out from the main scope that data was discovered.

For example, if your target is, would have a scope distance of 0 (i.e. in-scope). If BBOT discovers that resolves to, is one hop away, which means it would have a scope distance of 1. If has a PTR record that points to, is two hops away, so its scope distance is 2.

Scope distance continues to increase the further out you get. Most modules (e.g. nuclei and nmap) only consume in-scope events. Certain other passive modules such as asn accept out to distance 1. By default, DNS resolution happens out to a distance of 2. Upon its discovery, any event that's determined to be in-scope (e.g. immediately becomes distance 0, and the cycle starts over.

Displaying Out-of-scope Events

By default, BBOT only displays in-scope events (with a few exceptions such as STORAGE_BUCKETs). If you want to see more, you must increase the config value of scope_report_distance:

# display out-of-scope events up to one hop away from the main scope
bbot -t -f subdomain-enum -c scope_report_distance=1

Strict Scope

If you want to scan only that specific target hostname and none of its children, you can specify --strict-scope.

Note that --strict-scope only applies to targets and whitelists, but not blacklists. This means that if you put in your blacklist, you can be sure none of its subdomains will be scanned, even when using --strict-scope.

Whitelists and Blacklists

BBOT allows precise control over scope with whitelists and blacklists. These both use the same syntax as --target, meaning they accept the same event types, and you can specify an unlimited number of them, via a file, the CLI, or both.

--whitelist enables you to override what's in scope. For example, if you want to run nuclei against, but stay only inside their corporate IP range of, you can accomplish this like so:

# Seed scan with, but restrict scope to
bbot -t --whitelist -f subdomain-enum -m nmap nuclei --allow-deadly

--blacklist takes ultimate precedence. Anything in the blacklist is completely excluded from the scan, even if it's in the whitelist.

# Scan, but exclude and its children
bbot -t --blacklist -f subdomain-enum -m nmap nuclei --allow-deadly

DNS Wildcards

BBOT has robust wildcard detection built-in. It can reliably detect wildcard domains, and will tag them accordingly:

[DNS_NAME]   TARGET  (a-record, a-wildcard-domain, aaaa-wildcard-domain, wildcard-domain)
                                               ^^^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^

Wildcard hosts are collapsed into a single host beginning with _wildcard:

[DNS_NAME]     TARGET  (a-record, a-wildcard, a-wildcard-domain, aaaa-record, aaaa-wildcard, aaaa-wildcard-domain, wildcard, wildcard-domain)

If you don't want this, you can disable wildcard detection on a domain-to-domain basis in the config:


There are certain edge cases (such as with dynamic DNS rules) where BBOT's wildcard detection fails. In these cases, you can try increasing the number of wildcard checks in the config:

# default == 10
dns_wildcard_tests: 20

If that doesn't work you can consider blacklisting the offending domain.