Pro

Developer API

Unshorten links, trace redirect chains, and run security checks programmatically. All API features require a Pro key.

Authentication

Pass your Pro key in the Authorization header of every request.

HTTP header
Authorization: Bearer pro_your_key_here
        

Your Pro key is delivered by email after purchase and shown once on the success page. Keep it safe — it grants access to your daily quota.

Rate limits

Rate limits are enforced per Pro key using a sliding 24-hour window. Each URL counts as one check, including individual items in a bulk request.

Plan Limit Window
Free (UI only) 30 checks 24 hours
Pro 500 checks 24 hours

Rate limit headers are included in every response: X-RateLimit-Remaining and X-RateLimit-Reset (Unix ms timestamp).

Endpoints

POST /api/v1/unshorten

Unshorten a single URL. Traces the redirect chain, runs security checks, and optionally strips tracking parameters. Returns a shareable result link.

Request body

Field Type Default Description
url * string URL to unshorten (must start with http:// or https://)
clean boolean false Strip tracking parameters (utm_*, fbclid, gclid, etc.)
maxHops number 15 Maximum redirects to follow (1–15)
requestTimeout number 5000 Per-hop timeout in milliseconds

Response

200 OK
{
  "inputUrl": "https://bit.ly/example",
  "finalUrl": "https://example.com/article?id=123",
  "finalDomain": "example.com",
  "chain": [
    { "url": "https://bit.ly/example", "status": 301, "location": "https://example.com/article?id=123", "ms": 87 },
    { "url": "https://example.com/article?id=123", "status": 200, "ms": 210 }
  ],
  "flags": [
    { "code": "KNOWN_SHORTENER", "message": "Input is a known shortener domain" }
  ],
  "shareUrl": "https://unshorten.app/share?d=..."
}
              
            

Examples

curl

curl -X POST https://unshorten.app/api/v1/unshorten \
  -H "Authorization: Bearer pro_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://bit.ly/example","clean":true}'
                  
                

JavaScript

const res = await fetch('https://unshorten.app/api/v1/unshorten', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer pro_your_key_here',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ url: 'https://bit.ly/example', clean: true }),
});

const data = await res.json();
console.log(data.finalUrl);
                  
                

Python

import requests

res = requests.post(
    'https://unshorten.app/api/v1/unshorten',
    headers={'Authorization': 'Bearer pro_your_key_here'},
    json={'url': 'https://bit.ly/example', 'clean': True},
)

data = res.json()
print(data['finalUrl'])
                  
                
POST /api/v1/unshorten/bulk

Unshorten up to 200 URLs in a single request. Each URL is processed concurrently and counts as one check against your daily limit. Results are returned in the same order as the input.

Request body

Field Type Default Description
urls * string[] Array of URLs to unshorten (max 200)
clean boolean false Strip tracking parameters from all results
maxHops number 15 Maximum redirects per URL (1–15)
requestTimeout number 5000 Per-hop timeout in milliseconds

Response

200 OK
{
  "results": [
    {
      "inputUrl": "https://bit.ly/example1",
      "finalUrl": "https://example.com/page",
      "finalDomain": "example.com",
      "chain": [...],
      "flags": []
    },
    {
      "inputUrl": "https://invalid-url",
      "error": "Provide http(s) URL."
    }
  ],
  "processed": 2,
  "failed": 1
}
              
            

Examples

curl

curl -X POST https://unshorten.app/api/v1/unshorten/bulk \
  -H "Authorization: Bearer pro_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"urls":["https://bit.ly/a","https://t.co/b"],"clean":true}'
                  
                

JavaScript

const res = await fetch('https://unshorten.app/api/v1/unshorten/bulk', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer pro_your_key_here',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    urls: ['https://bit.ly/a', 'https://t.co/b'],
    clean: true,
  }),
});

const { results } = await res.json();
results.forEach(r => console.log(r.inputUrl, '->', r.finalUrl ?? r.error));
                  
                

Python

import requests

res = requests.post(
    'https://unshorten.app/api/v1/unshorten/bulk',
    headers={'Authorization': 'Bearer pro_your_key_here'},
    json={
        'urls': ['https://bit.ly/a', 'https://t.co/b'],
        'clean': True,
    },
)

for r in res.json()['results']:
    print(r['inputUrl'], '->', r.get('finalUrl', r.get('error')))
                  
                

Response fields

inputUrl

The URL you submitted, normalised.

finalUrl

The resolved destination after all redirects.

finalDomain

Hostname of the final URL (e.g. example.com).

chain

Array of hops. Each hop has url, status, optional location, and ms (latency).

flags

Security warnings. Each flag has a code and message.

shareUrl

Shareable link to view these results on unshorten.app. Only present in the single-URL endpoint.

Security flags

Flags are heuristic signals, not verdicts. A flagged URL may be legitimate; an unflagged URL may still be dangerous. Use them as a first-pass filter.

PUNYCODE_DOMAINCREDENTIALS_IN_URLAT_SYMBOLIP_DOMAINPRIVATE_IP_DOMAINSUSPICIOUS_PORTVERY_LONG_URLVERY_LONG_QUERYMANY_QUERY_PARAMSMIXED_SCRIPT_DOMAINLOOKS_LIKE_HOMOGRAPHKNOWN_SHORTENERSUSPICIOUS_TLDNON_HTTPS_FINALDOWNLOAD_FILETOO_MANY_REDIRECTSMAX_HOPS_REACHED

Errors

HTTP status error code Meaning
400 BAD_JSON Request body is not valid JSON.
400 BAD_REQUEST Invalid URL, forbidden host, or other input error. Check message.
401 UNAUTHORIZED Missing or invalid Pro key.
429 RATE_LIMITED Daily limit reached. Check X-RateLimit-Reset for when the window resets.