API documentation

The portscan.com API checks open TCP ports on a server programmatically. No API key, no authentication, and no signup required. The scan target is always the IP address of the server making the API request, determined from the connection itself. This makes the API suitable for servers checking their own port exposure, CI/CD pipelines verifying firewall rules, and monitoring scripts confirming expected services are reachable.

Both IPv4 and IPv6 are supported. Port 25 (SMTP) is included in every scan, unlike most cloud-hosted alternatives where outbound port 25 is blocked.

Quick start

Run from the server to be scanned:

# Start a fast scan
curl -X POST https://api.portscan.com/v1/fast

# Poll for results
curl https://api.portscan.com/v1/fast

The API scans the IP address the curl request originates from. Running these commands from a local workstation scans the workstation’s public IP. Running them from a cloud server scans the server’s IP.

Endpoints

Method Path Description
POST /v1/fast Start a fast scan (30 ports)
POST /v1/deep Start a deep scan (65,535 ports)
GET /v1/fast Poll fast scan results
GET /v1/deep Poll deep scan results

Scan duration

Typical wall-clock time after the scan actually starts is about 8 to 20 seconds for a fast scan and about 30 to 60 seconds for a deep scan. When the scanner queue is busy, extra waiting time can occur between POST and the start of scanning.

The eta_seconds field in the queued response is an indicative hint for polling intervals, not a guarantee of total time from POST to completion. Poll until status is complete or failed.

Responses

200 Scan submitted

Returned by POST when a scan is queued.

{
  "ip": "203.0.113.42",
  "scan_type": "fast",
  "status": "queued",
  "eta_seconds": 8
}

eta_seconds is a rough lower bound for the scanning phase; real-world duration often falls in the ranges in Scan duration above.

200 Scan complete

Returned by GET when results are ready.

{
  "ip": "203.0.113.42",
  "scan_type": "fast",
  "status": "complete",
  "ports_open": [
    {"port": 22, "state": "open", "service": "SSH", "banner": null},
    {"port": 80, "state": "open", "service": "HTTP", "banner": null},
    {"port": 443, "state": "open", "service": "HTTPS", "banner": null}
  ],
  "ports_filtered": [],
  "service_banners": {},
  "ptr_record": "mail.example.com",
  "duration_ms": 6231,
  "completed_at": 1711940665,
  "expires_at": 1712027200
}

200 Scan failed

Returned by GET when a scan did not complete.

{
  "ip": "203.0.113.42",
  "scan_type": "deep",
  "status": "failed",
  "chunks_complete": 28,
  "total_chunks": 32,
  "fail_reason": "timeout"
}

200 No scan found

Returned by GET when no scan exists for this IP.

{
  "ip": "203.0.113.42",
  "scan_type": "fast",
  "status": "none"
}

Error responses

Status Error Description
403 not_available IP is opted out or restricted
409 conflict Scan already running for this IP
422 invalid_target IP is RFC 1918, loopback, or otherwise non-routable
429 rate_limited Too many requests. Check Retry-After header.

Response headers

Header When Value
Retry-After On 429 responses Seconds until rate limit resets
X-RateLimit-Limit All responses Maximum requests in the current window
X-RateLimit-Remaining All responses Requests remaining in the current window
X-RateLimit-Reset All responses Unix timestamp when the rate limit resets
X-Scan-Duration-Ms Completed scan GET responses Scan duration in milliseconds

Webhook

Pass a URL as the X-Callback-Url header to receive a POST notification when the scan completes or fails.

curl -X POST https://api.portscan.com/v1/fast \
  -H "X-Callback-Url: https://myserver.com/hook"

The webhook fires on both completion and failure. Webhook and polling are fully complementary and work regardless of whether a callback URL was provided.

Rate limits

Scope Limit Window
Fast scan 200 per ASN 1 hour
Deep scan 1 per IP, 20 per ASN 5 minutes (IP), 1 hour (ASN)
Edge limit 30 requests per IP 1 minute

Rate-limited responses return HTTP 429 with a Retry-After header.

Common use cases

Server hardening check. After configuring a firewall, run a fast scan from the server to confirm only intended ports are open. Add the curl command to a post-deployment script.

Mail server verification. Check whether port 25 is open and reachable from outside the network. Most cloud-hosted scanners block port 25, making this test impossible from those platforms.

CI/CD integration. Add a port scan step to deployment pipelines. POST to start a scan, poll until complete, and fail the pipeline if unexpected ports are found open.

Monitoring. Periodically check a server’s port exposure with a cron job. Use the webhook callback to receive results without polling.

Limitations

The API scans the IP of the requesting server only. There is no parameter for specifying a different target IP. This is enforced at the server level and cannot be bypassed. The API is designed for self-checking, not for scanning third-party infrastructure.

UDP scanning is not supported. All scans are TCP only.

Scan results expire after 24 hours. Poll for results within this window.

Terms and policies

Usage of the API is subject to the portscan.com Terms of Service and Privacy Policy. For abuse reports or questions, see the Abuse contact page. To opt out an IP or range, visit Opt-out.