Speed up Nmap scans by running them in parallel.
2-6 times faster than native nmap scans, but with the same output. Nparallel starts multithreaded scans with one host per thread.
See About speed and reliability for detailed information about how this was measured.
even more:
- use native nmap arguments
- interrupt and continue scans at any time
- reduce and extend target list without having to scan finished hosts with the same command again
- depenedency free for almost all features
- additional stdout output format
-ol/out-log - export all hosts with open ports as
- .CSV with
-oC/out-csv - .XLSX with
-oE/out-excel(requires external lib) - .DOCX with
-oW/out-word(requires external lib)
- .CSV with
# Variant A: Download and install
git clone https://github.com/RonnyDo/nparallel
cd nparallel
pip install . # zero dependency installation
pip install .[with_office_export] # install external libs
# Variant B: Download and use raw script
wget https://raw.githubusercontent.com/RonnyDo/nparallel/refs/heads/main/nparallel/nparallel.py
# Usage: nparallel nmap [nmap-args] -iL TARGETS_FILE
$ nparallel nmap -v --top-ports 100 -oX results.xml -iL targets.txt
[*] Cmd id: cabb60dc | Nmap base cmd: nmap -v --top-ports 100 -oX results.xml | Threads: 32
[*] Start: 21:49:03
[+] Progress: 3/3 hosts
[+] End: 21:49:06 (Finished in 3.11 seconds)
[+] XML file saved at '/home/user/results.xml'
Hint: The minimum number of threads used by nparallel should be equal to the amount of cores the system offers. Less threads lead to a slower performance. More threads doesn't increase the performance but can be better, because sometimes hosts become unresponsive and block single threads. The amount of threads can be set with --threads <num>.
# list all scans
$ nparallel ls
[*] Cache contains 3 scans:
Cmd id Finished Nmap base command
--- --- ---
ab4e8efa 3 nmap -T4 -v --top-ports 10
9d9c55a7 1 nmap -T5
c178e8fa 64 nmap -T4 -v --top-ports 100
# show scan details of scan with cmd id 'ab4e8efa'
$ nparallel ls ab4e8efa
[*] Nmap base command:
ab4e8efa: nmap -T4 -v --top-ports 10
[+] Hosts finished (3):
45.33.32.156 127.0.0.1 172.1.2.3
[+] Hosts with open ports (2):
45.33.32.156 127.0.0.1
[+] Ports open TCP (3):
22,80,443
[+] Ports open UDP (1):
69
# show merged scan details of scans with cmd ids 'ab4e8efa' and '9d9c55a7'
$ nparallel ls ab4e8efa 9d9c55a7
[*] Nmap base command:
ab4e8efa: nmap -T4 -v --top-ports 10
9d9c55a7: nmap -T5
[+] Hosts finished (3):
45.33.32.156 127.0.0.1 172.1.2.3
[+] Hosts with open ports (2):
45.33.32.156 127.0.0.1 140.40.40.4
[+] Ports open TCP (3):
22,80,443,444
[+] Ports open UDP (1):
69
# Delete only scan with cmd id 'ab4e8efa'
$ python3 nparallel.py rm ab4e8efa
[+] Entry with cmd_id 'ab4e8efa' removed
# delete entire cache
$ nparallel rm
[?] Delete entire cache? [y/N]y
[+] Cache cleared.
The following happens under the hood when running nparallel nmap -v --top-ports 100 -oX results.xml -iL targets.txt:
- Resolve all entries of
targets.txtinto single hosts. IP addresses, URLs and CIDR notation (e.g. 172.1.2.0/24) are supported. - Check which hosts haven't been scanned by the provided nmap argument set yet, by checking the
.cache/<cmd_id>directory. Each nmap argument set has a different id ("cmd_id"). The argument order doesn't matter. If the argument set changes, nparallel runs a new scan. Changing only the arguments listednparallel nmap -hbut keep the other nmap arguments untouched, does not lead to a new scan. - Start parallel nmap scans of all unfinished scans. Each scan/thread scans exactly one host.
- Wait until all scans have finished.
- If an output parameter is provided (
-oA/-oX/-oN/-oG/-oL/-oE/-oW) the per host scan results get merged into a single output file. The output file should be™ 99 % identical with a "normal" nmap result file. However some meta information might be shortened or missing.