Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?


Failed to load latest commit information.
Latest commit message
Commit time
January 18, 2023 18:09
March 31, 2021 19:09
January 18, 2023 18:09
March 21, 2021 02:09
January 18, 2023 18:09
October 6, 2021 10:12
January 18, 2023 18:09
January 18, 2023 18:09

Knock Subdomain Scan v6.1.0

Knockpy is a portable and modular python3 tool designed to quickly enumerate subdomains on a target domain through passive reconnaissance and dictionary scan.


Very simply


Table of Contents


Run from folder

You need python3, pip3, git.
git clone
cd knock
pip3 install -r requirements.txt

python3 <DOMAIN>

Install package

As root
git clone
cd knock
python3 install

knockpy <DOMAIN>


Knockpy image hosted at DockerHub Page and automatically updated with RAUDI

docker run -it --rm secsi/knockpy <domain>


As a standalone command line tool

Knockpy -h

usage: knockpy [-h] [-v] [--no-local] [--no-remote] [--no-scan] [--no-http] 
               [--no-http-code CODE [CODE ...]] [--dns DNS] [-w WORDLIST] 
               [-o FOLDER] [-t SEC] [-th NUM] [--silent [{False,json,json-pretty,csv}]]

full scan:    knockpy
quick scan:   knockpy --no-local
faster scan:  knockpy --no-local --no-http
ignore code:  knockpy --no-http-code 404 500 530
silent mode:  knockpy --silent

show recon:   knockpy --no-local --no-scan

show report:  knockpy --report knockpy_report/domain.com_yyyy_mm_dd_hh_mm_ss.json
plot report:  knockpy --plot knockpy_report/domain.com_yyyy_mm_dd_hh_mm_ss.json
csv report:   knockpy --csv knockpy_report/domain.com_yyyy_mm_dd_hh_mm_ss.json

positional arguments:
  domain                target to scan

optional arguments:
  -h, --help            show this help message and exit
  -v, --version         show program's version number and exit
  --no-local            local wordlist ignore
  --no-remote           remote wordlist ignore
  --no-scan             scanning ignore, show wordlist and exit
  --no-http             http requests ignore
  --no-http-code CODE [CODE ...]
                        http code list to ignore

  --dns DNS             use custom DNS ex.                        

  -w WORDLIST           wordlist file to import
  -o FOLDER             report folder to store json results
  -t SEC                timeout in seconds
  -th NUM               threads num

  --silent [{False,json,json-pretty,csv}]
                        silent or quiet mode, default: False

Full scan

$ knockpy
  • Scan type: dns + http(s) requests
  • Wordlist: local + remote

Knockpy uses by default a internal file wordlist.txt and a remote list obtained by scanning other sources (passive recon) through plugins. To use a custom dictionary you can use the -w option and specify the path to your local dictionary. Also, you can write a new plugin to populate the wordlist with subdomains obtained from external services. Take a look at the ones in the remote folder and use them as an example. Remember that some plugins, like Virustotal or Shodan, need apikey to work.

The domain target can be passed via STDIN.

echo "" | knockpy

To ignore http(s) responses with specific code, you can use the --no-http-code followed by the code list 404 500 530. With the --no-ip option you can ignore ip list 192.168.101

Scan with remote list only: --no-local

$ knockpy --no-local
  • Scan type: dns + http(s) requests
  • Wordlist: remote

Only test subdomains obtained through passive reconnaissance using plugins. This scanning mode will be faster because it excludes the local dictionary.

No scan, get remote list only: --no-local --no-scan

$ knockpy --no-scan --no-local
  • Scan type: none
  • Wordlist: remote list

Print passive-only wordlist and exit. No scan will be performed.

Use a custom DNS: --dns

$ knockpy --dns

By default it uses the pre-configured DNS on your system (ex. /etc/resolv.conf).

Silent mode: --silent

$ knockpy --silent

Hide terminal output and save json report in the output folder. Using --silent with the --no-scan option hides the banner and shows the list of subdomains to the terminal.

$ knockpy --silent json

Hide terminal output and print final results in json format.

$ knockpy --silent json-pretty

Hide terminal output and print final results in intented json.

$ knockpy --silent csv

Hide terminal output and print final results in csv format.

Note that at each scan the report will be automatically saved.

Output folder: -o

$ knockpy -o /path/to/new/folder

All scans are saved in the default folder knockpy_report. Alternatively, you can use the -o /path/folder to define the new folder path or disable autosave using -o false.


At each scan the report will be automatically saved in json format inside the file with the name domain.com_yyyy_mm_dd_hh_mm_ss.json. If you don't like autosave you can disable using -o false.

Report example domain.com_yyyy_mm_dd_hh_mm_ss.json:

    "": {
        "domain": "host.domain.ext",
        "alias": [""],
        "ipaddr": [
        "code": 200,
        "server": "Microsoft-IIS/8.5"
               -- cut --
        "domain": "",
        "alias": [],
        "ipaddr": [
        "code": 500,
        "server": "nginx/1.15.6 "
    "_meta": {
        "name": "knockpy",
        "version": "5.4.1",
        "time_start": 1616353591.2510355,
        "time_end": 1616353930.6632543,
        "domain": "",
        "wordlist": 2120

_meta is a reserved key that contains the basic information of the scan.

Show report: --report

$ knockpy --report knockpy_report/domain.com_yyyy_mm_dd_hh_mm_ss.json

Print the report in the terminal in a human format.

Convert report in CSV: --csv

$ knockpy --csv knockpy_report/domain.com_yyyy_mm_dd_hh_mm_ss.json

Save the existing report in csv file.

Plot report: --plot

$ knockpy --plot knockpy_report/domain.com_yyyy_mm_dd_hh_mm_ss.json
  • Plot relationships.

Plot needs these libraries:

  • matplotlib
  • networkx
  • PyQt5



Usage as a library

Importing knockpy as a module (dependence) in your python script is quite simple. Naturally, the package must be installed on your system.

from knockpy import knockpy

The command-line parameters can be managed with the following dictionary.

params = {
    "no_local": False,  # [bool] local wordlist ignore
    "no_remote": False, # [bool] remote wordlist ignore
    "no_scan": False,   # [bool] scanning ignore, show wordlist
    "no_http": False,   # [bool] http requests ignore
    "no_http_code": [], # [list] http code list to ignore
    "no_ip": [],        # [list] ip address to ignore
    "dns": "",          # [str] use custom DNS ex.
    "timeout": 3,       # [int] timeout in seconds
    "threads": 30,      # [int] threads num
    "useragent": "",    # [str] use a custom user agent
    "wordlist": ""      # [str] path to custom wordlist

You can choose pass only the keys you want to change and keep the others with the default values. Eg:

params = {
    "no_local": True,
    "no_scan": True

Then you can call the function knockpy.Scanning.start() passing as values the domain and the dictionary assigned to the variable params to get the results in json format.

results = knockpy.Scanning.start("", params)


Write your own plugin

The plugins are situated in remote folder. If you want to write your own plugin it's important to pay attention to some precautions:

  • if apikey is required, use api_ before the plugin name:
  • the function name must be get and take as parameter domain:
    def get(domain):
  • the function must return a possibly unique list of subdomains:
    ['', '', ...]
  • to parse/scrape the results it is recommended to use the standard modules such as:
    requests, json, bs4, re

Here is an example of how a plugin should be structured. You can find other examples in the remote folder.

import requests
import json

def get(domain):
    # servicename -> JSON: key -> subdomain
    url = "{domain}".format(domain=domain)
    resp = requests.get(url, timeout=5).text
    resp = json.loads(resp)
    result = []
    for item in resp['data']:
        subdomain = item['subdomain']
        if subdomain not in result:

    return result

Plugin test --plugin-test

$ knockpy --plugin-test

In this example, the output shows errors 'error': True in three plugins because they need the API key.

    '': {
        'time': '00:00:03',
        'match': 0,
        'error': True
    '': {
        'time': '00:00:00',
        'match': 9,
        'error': False
    '': {
        'time': '00:00:00',
        'match': 44,
        'error': False
    '': {
        'time': '00:00:00',
        'match': 9,
        'error': False
    '': {
        'time': '00:00:19',
        'match': 10,
        'error': False
    '': {
        'time': '00:00:03',
        'match': 0,
        'error': True
    '': {
        'time': '00:00:04',
        'match': 4,
        'error': False
    '': {
        'time': '00:00:03',
        'match': 0,
        'error': True
    '': {
        'time': '00:00:01',
        'match': 11,
        'error': False
    '_results': {
        'time': '00:00:37',
        'plugins': {
            'count': 9,
            'list': ['', '', '', '', ...],
            'error': ['', '', '']
        'subdomains': {
            'count': 52,
            'list': ['admin', 'cloud', 'www', 'mail', 'calendar', 'contact', 'ftp', .....]


Knockpy is currently under development by @guelfoweb and it's released under the GPL 3 license.