POST/api/v1/phishing/url-expand

URL Expand

Follow a URL through its entire redirect chain to reveal the final destination. Useful for unshortening links and detecting suspicious multi-hop redirects often used in phishing campaigns.

Credits

1

Per request

Max Hops

10

5s timeout per hop

Plans

All

Free, Starter, Professional, Enterprise

Behavior & Security

FeatureDetail
Max redirects10 hops — returns an error if exceeded
Timeout per hop5 seconds — slow servers are treated as dead ends
SSRF protectionRedirects to private/internal IPs (RFC 1918, loopback, link-local) are blocked
Suspicious flagChains with more than 3 hops are automatically marked suspicious
Hop detailsEach hop reports the status code, server header, and location header

SSRF protection ensures the API cannot be abused to scan internal networks. If any hop in the chain resolves to a private IP address, the chain is terminated and an error is returned for that hop.

Request Body

FieldTypeRequiredDescription
urlstringYesThe URL to expand (follow redirects)

Code Examples

cURL

curl -X POST https://dfir-lab.ch/api/v1/phishing/url-expand \
  -H "Authorization: Bearer sk-dfir-your-key-here" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://bit.ly/3xYzAbC"
  }'

Python

import requests

response = requests.post(
    "https://dfir-lab.ch/api/v1/phishing/url-expand",
    headers={
        "Authorization": "Bearer sk-dfir-your-key-here",
        "Content-Type": "application/json",
    },
    json={
        "url": "https://bit.ly/3xYzAbC"
    },
)

data = response.json()
print(f"Final URL: {data['final_url']}")
print(f"Hops: {data['total_hops']}")
print(f"Suspicious: {data['suspicious']}")

for i, hop in enumerate(data["hops"], 1):
    print(f"  {i}. [{hop['status_code']}] {hop['url']}")

Example Response

Standard redirect chain (not suspicious)

{
  "success": true,
  "original_url": "https://bit.ly/3xYzAbC",
  "final_url": "https://www.example.com/landing-page?ref=campaign",
  "total_hops": 2,
  "suspicious": false,
  "hops": [
    {
      "hop": 1,
      "url": "https://bit.ly/3xYzAbC",
      "status_code": 301,
      "server": "bit.ly",
      "location": "https://www.example.com/landing-page?ref=campaign"
    },
    {
      "hop": 2,
      "url": "https://www.example.com/landing-page?ref=campaign",
      "status_code": 200,
      "server": "nginx",
      "location": null
    }
  ],
  "credits_used": 1,
  "credits_remaining": 486
}

Suspicious redirect chain (>3 hops)

{
  "success": true,
  "original_url": "https://t.co/aB1cD2eF3g",
  "final_url": "https://phishing-site.example.com/login",
  "total_hops": 5,
  "suspicious": true,
  "suspicious_reason": "Redirect chain exceeds 3 hops",
  "hops": [
    {
      "hop": 1,
      "url": "https://t.co/aB1cD2eF3g",
      "status_code": 301,
      "server": "tsa_b",
      "location": "https://shortener2.example.com/r/abc123"
    },
    {
      "hop": 2,
      "url": "https://shortener2.example.com/r/abc123",
      "status_code": 302,
      "server": "cloudflare",
      "location": "https://redirect3.example.net/go?u=xyz"
    },
    {
      "hop": 3,
      "url": "https://redirect3.example.net/go?u=xyz",
      "status_code": 302,
      "server": "Apache/2.4",
      "location": "https://tracker.example.org/click?id=9876"
    },
    {
      "hop": 4,
      "url": "https://tracker.example.org/click?id=9876",
      "status_code": 301,
      "server": "openresty",
      "location": "https://phishing-site.example.com/login"
    },
    {
      "hop": 5,
      "url": "https://phishing-site.example.com/login",
      "status_code": 200,
      "server": "nginx",
      "location": null
    }
  ],
  "credits_used": 1,
  "credits_remaining": 485
}