Skip to main content
The Scope page manages the set of IP addresses that multi-target scans operate on. Entries can be added as individual IPs, CIDR blocks, or dash-notation ranges. All formats are expanded to individual IPs at import time and stored with scan status tracking.

Database schema

Scope entries are stored in the scope table in data/reaper.db.
ColumnTypeDescription
idINTEGERPrimary key, auto-incremented
ipTEXT UNIQUEExpanded individual IP address
cidrTEXTOriginal CIDR input if the entry came from CIDR notation (e.g. 192.168.1.0/24)
ip_rangeTEXTOriginal range input if the entry came from a range (e.g. 192.168.1.1-200)
statusTEXTScan status: pending or scanned
notesTEXTOptional notes
added_atTIMESTAMPWhen the entry was added
scanned_atTIMESTAMPWhen the entry was last scanned
One row is created per expanded IP. The cidr or ip_range column retains the original input so you can see which block an IP belongs to.

Input normalization

All scope import endpoints pass input through the normalize_scope_entry() function, which handles three formats:
FormatExampleHandled by
Single IP192.168.1.1Python ipaddress.ip_address() validation
CIDR block192.168.1.0/24expand_cidr() — uses ipaddress.ip_network(...).hosts()
IP range192.168.1.1-200expand_ip_range() — splits on last ., expands last octet range
Lines beginning with # and blank lines are ignored. Entries that fail all three format checks are returned in the invalid array of the response.
CIDR expansion uses strict=False, so host bits in the input are silently zeroed. 192.168.1.5/24 is treated as 192.168.1.0/24.

API endpoints

List scope entries

GET /api/scope
Returns all scope entries ordered by added_at descending. Response
{
  "status": "success",
  "scope": [
    {
      "id": 1,
      "ip": "10.10.10.5",
      "cidr": "10.10.10.0/24",
      "ip_range": null,
      "status": "scanned",
      "notes": null,
      "added_at": "2024-01-15 10:00:00",
      "scanned_at": "2024-01-15 12:34:56"
    }
  ]
}

Import from file upload

POST /api/scope/import
Content-Type: multipart/form-data
Uploads a text file containing one target per line. Each line is passed through normalize_scope_entry(). CIDR and ranges are expanded to individual IPs before insertion. Duplicate IPs (INSERT OR IGNORE) are silently skipped. Response
{
  "status": "success",
  "imported": 254,
  "total_ips": 254,
  "invalid": []
}

Add targets manually

POST /api/scope/add-manual
Request body
{
  "targets": "192.168.1.1\n192.168.1.0/24\n10.10.10.1-50"
}
Accepts a newline-separated string. Same normalization and deduplication logic as the file upload endpoint.

Add from local file path

POST /api/scope/add-local-file
Request body
{ "file_path": "/home/user/targets.txt" }
Reads a file from the server’s local filesystem. Useful when the targets file is already on the machine running EtherReaper. Returns a 404 if the file does not exist. Response
{
  "status": "success",
  "imported": 10,
  "total_ips": 10,
  "invalid": [],
  "file_path": "/home/user/targets.txt"
}

Delete a scope entry

DELETE /api/scope/{scope_id}

Bulk delete scope entries

POST /api/scope/bulk-delete
Request body
{ "ids": [1, 2, 3] }

Clear all scope

DELETE /api/scope/clear
Deletes every row in the scope table. Returns the count of deleted entries.
Clearing scope does not delete host records. Previously scanned hosts remain in the Hosts database.

Scope status tracking

Each IP starts with status = 'pending'. When an Nmap scan completes and its XML is parsed, any scope entry whose IP appears in the results is updated to status = 'scanned' with a scanned_at timestamp. The scope-unscanned host type filter (GET /api/hosts/by-type/scope-unscanned) returns IPs that are in scope but have no matching host record — a convenient way to identify targets that have not been scanned yet.

How scope feeds into multi-target scans

The following scan types use scope as their target source:
  • SMB Signing Check — iterates scope IPs to identify unsigned relay targets
  • Coerce — supports multi-target mode by iterating scope IPs
  • Web Screenshots (From Database → All Hosts) — uses all IPs from the hosts table, which is populated from scope scans
  • Masscan — can be pointed at a CIDR derived from scope
Scans that use scope IPs retrieve them via GET /api/hosts/by-type/all or GET /api/hosts/by-type/scope-unscanned rather than directly reading the scope table.

Build docs developers (and LLMs) love