URL Resolver API & Scraper
The URL Resolver API follows and analyzes links as clean JSON.
🤖 Using an AI assistant? Copy this link into ChatGPT / Claude / Cursor — it reads every endpoint and parameter instantly and tells you if this API fits your use case.
The primary resolve endpoint returns the redirect chain (URL, status, host, resolved IPs) to the final URL and domain, and you can normalize, detect an affiliate link, get a product_hint, a preview, a safety check and a full analysis. It is built for link analysis, affiliate tools and moderation that need to know where a link really goes. One ReefAPI key, one shared credit pool, the standard envelope.
What each block gives you, with measured output
Seven actions read one URL from different angles, and full returns every block in a single call. The examples are two measured runs: a bit.ly short link, and an Amazon product URL carrying both an affiliate tag and a UTM parameter.
| Action | Key fields | Measured output |
|---|---|---|
| resolve | final_url, redirect_chain[] (url, status, host, resolved_ips), status_codes[], hop_count, is_short_link, redirect_loop, stop_reason | the bit.ly link: hop_count 0, status 200, is_short_link true, stop_reason "complete" |
| normalize | canonical_url, cleaned_url, stripped_tracking_params[], detected_platform, page_title | stripped_tracking_params ["utm_source"] — and tag=test-20 deliberately kept |
| detect_affiliate | is_affiliate, affiliate_type, affiliate_network, affiliate_params, merchant_hint, all_networks[] | network "amazon_associates", params {tag: "test-20"}, merchant_hint "amazon" |
| product_hint | marketplace, possible_product_id, engine_hint, is_product_url | marketplace "amazon", possible_product_id "B08N5WRWNW", engine_hint "amazon" |
| preview | title, description, image, site_name, type, card, favicon, has_opengraph | title from the page; has_opengraph false when the page publishes no OG tags |
| safety | risk_level, risk_score, flags[], domain_changed, final_is_https, threat_intel | a plain http:// URL scored 22, risk_level "low", flags ["non_https_final"] |
| full / batch | every block merged / one resolve block per URL | use full for one link, batch for a list |
engine_hint is the useful part of product_hint: it names the ReefAPI engine that can fetch that product, so an unknown link becomes a routed call without you writing a domain-to-engine map. Measured, an Amazon URL returned engine_hint "amazon".
Real request and response JSON
Captured from the indexed primary action, resolve, on .
{
"method": "POST",
"url": "https://api.reefapi.com/url-resolver/v1/resolve",
"headers": {
"x-api-key": "$REEF_KEY",
"content-type": "application/json"
},
"body": {
"url": "http://github.com"
}
}{
"ok": true,
"meta": {
"api": "url-resolver",
"endpoint": "resolve",
"mode": "live",
"latency_ms": 51,
"record_count": 1,
"bytes": 41,
"cache_hit": false,
"method": "manual_redirect_follow_curl_cffi_bare_dc",
"ssrf_guarded": true,
"hops": 0,
"stop_reason": "complete"
},
"data": {
"final_url": "http://github.com",
"final_domain": "github.com",
"redirect_chain": [
{
"url": "http://github.com",
"status": 200,
"host": "github.com",
"resolved_ips": [
"[redacted-phone]"
]
}
],
"status_codes": [
200
],
"hop_count": 0,
"content_type": null,
"is_short_link": false,
"redirect_loop": false,
"final_blocked": false,
"stop_reason": "complete"
}
}What the URL Resolver API does
| Action | Description | Concrete use case | Key params |
|---|---|---|---|
| resolve | Follow the redirect chain to the final URL (hop-by-hop, every status observable). | Ops teams call resolve to get follow the redirect chain to the final URL (hop-by-hop, every status observable).. | url, max_hops |
| normalize | Resolve then strip tracking params (utm_*/fbclid/gclid…) → canonical URL. | Developer tools call normalize to resolve then strip tracking params (utm_*/fbclid/gclid…) → canonical URL.. | url, follow |
| detect_affiliate | Detect the affiliate network/params/merchant across the whole redirect chain, incl. first-party brand programs (influencer/seller deeplinks). | Validation workflows call detect_affiliate to detect the affiliate network/params/merchant across the whole redirect chain, incl. | url, follow |
| product_hint | Identify marketplace + product-id + the ReefAPI engine that can fetch the product. | Data-quality teams call product_hint to get identify marketplace + product-id + the ReefAPI engine that can fetch the product.. | url, follow |
| preview | Link unfurl: OpenGraph + Twitter-card title/description/image/favicon (Slack/Discord style). | Ops teams call preview to get link unfurl. | url |
| safety | Heuristic URL-risk flags (ip-host, non-https, punycode, userinfo, high-abuse TLD, long/multi-shortener chain, cross-domain) + risk level/score. | Developer tools call safety to get heuristic URL-risk flags (ip-host, non-https, punycode, userinfo, high-abuse TLD, long/multi-…. | url |
| full | One call: resolve + normalize + detect_affiliate + product_hint + preview + safety. | Validation workflows call full to get one call. | url, max_hops |
| batch | Resolve up to 50 URLs concurrently in one call — each URL is validated and resolved independently. | Data-quality teams call batch to resolve up to 50 URLs concurrently in one call. | urls |
Call resolve from your stack
curl -X POST https://api.reefapi.com/url-resolver/v1/resolve \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"url":"http://github.com"}'import requests
r = requests.post(
"https://api.reefapi.com/url-resolver/v1/resolve",
headers={"x-api-key": REEF_KEY},
json={
"url": "http://github.com"
},
)
print(r.json()["data"])const res = await fetch("https://api.reefapi.com/url-resolver/v1/resolve", {
method: "POST",
headers: {
"x-api-key": process.env.REEF_KEY,
"content-type": "application/json",
},
body: JSON.stringify({
"url": "http://github.com"
}),
});
const { ok, data, meta, error } = await res.json();Ask your MCP-connected assistant: call reefapi.url-resolver.resolve with {"url":"http://github.com"}.Who uses this API and why
- Affiliate tools call detect_affiliate to identify and handle monetized links.
- Moderation uses safety to screen a shortened link before allowing it.
- Commerce uses product_hint to map a redirect to a product.
Questions developers ask before integrating
Why does cleaned_url still contain the affiliate tag?
Because cleaning removes analytics parameters, not attribution. Measured on an Amazon URL carrying both, stripped_tracking_params came back as ["utm_source"] while tag=test-20 survived into both canonical_url and cleaned_url. That is deliberate: silently deleting an affiliate tag would break someone's revenue attribution without telling them. If you want a genuinely bare URL, take the keys listed in affiliate.affiliate_params and remove them yourself — the response names them precisely so you can.
Is the safety block a malware or phishing check?
No, and it says so rather than implying otherwise. threat_intel returns status "phase2_needs_auth_key" with a note stating these are heuristic risk flags and not a malware database — real intelligence from abuse.ch URLhaus or Google Safe Browsing needs a key we do not ship. What you do get is honest structural signal: risk_score, flags such as non_https_final, domain_changed telling you the final host differs from the one you were given, and final_is_https. A measured plain-http URL scored 22 with one flag. Use it to triage, never as a security verdict.
A short link came back with status 200 — does that mean it resolved?
Not necessarily. A measured call on a bit.ly path that does not exist returned status 200, hop_count 0, final_url identical to the input and final_domain still bit.ly — the shortener served its own page rather than redirecting. Check hop_count and whether final_domain changed, not just the status code. is_short_link true combined with hop_count 0 is the signature of a dead or invalid short link.
Where does possible_product_id come from — the page or the URL?
The URL pattern, which is why it still works when the page does not. A measured Amazon link returned status 404 and page_title "Page Not Found", yet product_hint still extracted possible_product_id "B08N5WRWNW" and set is_product_url true, because the /dp/<ASIN>/ shape is unambiguous. That is useful — you can classify a link without a successful fetch — but it means the id is a well-formed candidate, not proof the product exists. Confirm it with the engine named in engine_hint.
What is in redirect_chain beyond the URLs?
Each hop carries its own url, HTTP status, host, content_type and resolved_ips, and that IP list includes IPv6 where the host publishes it — a measured hop returned six addresses across both families. status_codes[] is the same sequence flattened, which is what you want for a quick 301-versus-302 check. hop_count is the number of redirects, so zero means the URL you passed was already final. max_hops caps how far it will follow, and redirect_loop plus stop_reason tell you why it stopped.
How do I tell a first-party affiliate link from a network one?
affiliate_type separates them: "network" means a recognized affiliate network with named parameters, and "first_party" means the merchant's own referral scheme, reported through first_party_signals. all_networks[] handles the case where a chain passes through more than one, recording which host each was seen on. A measured Amazon Associates link returned affiliate_type "network", affiliate_network "amazon_associates" and a single entry in all_networks tagged with the host it came from.
Should I call full or the individual actions?
full when you have one link and want everything, because it merges resolve, normalize, affiliate, product, preview and safety into one response and one round trip. The individual actions are for volume: preview and safety both fetch the page, so calling them separately on a large list costs more than it needs to. batch is the third option, returning one resolve block per URL with its own ok flag plus count and ok_count, which is the right shape for cleaning a link table.
What is the URL Resolver API?
URL Resolver API is a ReefAPI endpoint group for url resolver It returns live JSON through POST requests under /url-resolver/v1.
Is the URL Resolver API free to try?
Yes. ReefAPI starts with 1,000 free credits, no card required. URL Resolver calls use the same shared credit balance as every other ReefAPI engine.
Do I need an URL Resolver login or account?
No login to URL Resolver is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.
How fresh is the URL Resolver data?
The page example is captured from a live resolve call, and production requests fetch live data through ReefAPI rather than a static sample.
How many credits does the URL Resolver API use?
URL Resolver actions currently cost 1 credit per successful call. Failed or blocked calls are free, and all APIs draw from one credit pool.
Can I call URL Resolver from an AI assistant or MCP client?
Yes. Connect ReefAPI once through MCP and your assistant can call url-resolver actions with the same key, credit pool and JSON envelope used by normal REST requests.
Is the URL Resolver API an URL Resolver scraper?
It is the managed alternative to a DIY URL Resolver scraper. Instead of building and maintaining your own scraper — proxies, headless browsers, captcha and constant breakage — you call one ReefAPI endpoint and get the same url resolver back as clean JSON.