How to Detect Suspicious URLs Programmatically
Detect suspicious URLs programmatically with parsing, normalization, redirect analysis, and metadata inspection — using real URL Inspector capabilities.
Security and agent teams often need programmatic URL analysis before allowing fetches, publishing links, or executing HTTP tools. "Suspicious" is not a single boolean — it is a set of signals: malformed syntax, disallowed schemes, redirect chains that land on unexpected hosts, HTTP errors, and metadata mismatches with claimed destinations.
This guide shows how to build a honest detection pipeline using real URL Inspector API capabilities — parsing, normalization, redirect analysis, and metadata inspection — without claiming malware or phishing verdicts the API does not provide.
What "suspicious" means in code
Define suspicion as policy-relevant anomalies, not omniscient threat detection:
| Signal | Example | Typical response |
|---|---|---|
| Parse failure | Invalid URL string | Reject before network |
| Disallowed scheme | javascript:, file: | Block |
| Private / metadata IP | http://169.254.169.254/ | Block (SSRF) |
| Redirect hop limit exceeded | >10 redirects | Review or block |
| Final host ≠ proposed host | Short URL → unknown domain | Review |
| Scheme downgrade | https → http redirect | Block |
| HTTP error | 404, 403, 5xx | Context-dependent |
| Title/metadata mismatch | "Sign in" title for docs link | Review (weak signal) |
Combine signals with weighted policy — none alone proves malice.
URL Inspector API overview
IdenticAPI exposes URL inspection via RapidAPI:
- Base host:
url-inspector.p.rapidapi.com - Endpoint:
GET /inspect?url={url_encoded} - Authentication:
X-RapidAPI-KeyandX-RapidAPI-Hostheaders
Documented capabilities include HTTP status, redirect chains, final resolved URL, and page metadata (such as HTML title). The API performs HTTP-level inspection — it does not execute JavaScript in a headless browser, scan for malware, or return phishing scores.
Product page: URL Inspector API.
Basic inspection request
curl -G "https://url-inspector.p.rapidapi.com/inspect" \
--data-urlencode "url=https://example.com" \
-H "X-RapidAPI-Key: YOUR_RAPIDAPI_KEY" \
-H "X-RapidAPI-Host: url-inspector.p.rapidapi.com"
Example response:
{
"url": "https://example.com",
"status": 200,
"final_url": "https://example.com/",
"redirects": [],
"title": "Example Domain"
}
Use status, redirects, final_url, and title as structured inputs to your policy engine.
Node.js integration example
type InspectResult = {
url: string;
status: number;
final_url: string;
redirects: Array<{ url: string; status: number }>;
title?: string;
};
async function inspectUrl(target: string): Promise<InspectResult> {
const endpoint = new URL("https://url-inspector.p.rapidapi.com/inspect");
endpoint.searchParams.set("url", target);
const res = await fetch(endpoint, {
headers: {
"X-RapidAPI-Key": process.env.RAPIDAPI_KEY!,
"X-RapidAPI-Host": "url-inspector.p.rapidapi.com"
}
});
if (!res.ok) throw new Error(`Inspector HTTP ${res.status}`);
return res.json() as Promise<InspectResult>;
}
Call from server-side agent orchestrators — not from browsers exposing keys.
Pre-inspection: parse and normalize
Run local checks before RapidAPI calls to save quota and block SSRF early:
function preflightUrl(raw: string): URL {
const url = new URL(raw.trim());
if (!["http:", "https:"].includes(url.protocol)) {
throw new Error("disallowed_scheme");
}
const host = url.hostname.toLowerCase();
const blocked = ["localhost", "127.0.0.1", "169.254.169.254"];
if (blocked.includes(host) || host.endsWith(".local")) {
throw new Error("blocked_host");
}
return url;
}
Apply tenant allowlists before inspection when URLs are already known-good.
Redirect analysis patterns
After inspection, evaluate redirect chain:
function analyzeRedirects(
proposed: string,
result: InspectResult,
opts: { maxHops: number; allowedFinalHosts: Set<string> }
): string[] {
const reasons: string[] = [];
if (result.redirects.length > opts.maxHops) {
reasons.push("redirect_limit_exceeded");
}
const finalHost = new URL(result.final_url).hostname.toLowerCase();
const proposedHost = new URL(proposed).hostname.toLowerCase();
if (finalHost !== proposedHost) {
reasons.push("final_host_differs");
}
if (!opts.allowedFinalHosts.has(finalHost)) {
reasons.push("final_host_not_allowlisted");
}
for (const hop of result.redirects) {
const hopUrl = new URL(hop.url);
if (hopUrl.protocol === "http:" && proposed.startsWith("https:")) {
reasons.push("scheme_downgrade");
}
}
return reasons;
}
Return reasons[] to logging and Agent Action Guard context — do not collapse to suspicious: true without detail.
Metadata as weak signals
title and meta fields support analyst UX:
- Display "Destination page title: …" before agent fetch
- Flag review when title contains "login", "password", "wallet" for non-auth workflows
Titles are attacker-controlled. Never auto-allow based on title alone.
Layering with agent policy
Inspection informs; policy enforces:
inspectUrl(url) → analyzeRedirects() → score reasons
↓
Agent Action Guard(tool, action, args, context)
↓
allow | review | block (runtime enforced)
Example guard call after inspection:
curl -X POST https://www.identicapi.com/api/v1/security/agent-action \
-H "Authorization: Bearer idapi_test_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"tool_name": "http_client",
"action": "get",
"arguments": { "url": "https://short.example/abc" },
"context": "inspect: final_host=unknown.example; redirects=2; reasons=final_host_differs"
}'
See Validate URLs Before AI Agents Open Them.
What to tell stakeholders
Honest capability statement:
- "We parse URLs, inspect HTTP status and redirects, and apply tenant policy."
- Not: "Our API detects all phishing links."
- Not: "Inspected URLs are malware-free."
For phishing-specific products, evaluate content and reputation signals separately — Phishing Detection API: What Developers Need.
Operational considerations
- Timeouts — set client timeouts; define fail-closed vs review on inspector outage
- Rate limits — cache inspection results by URL hash for short TTL where safe
- Public URLs only — inspector reaches public internet; combine with SSRF blocks for internal targets
- Logging — store proposed URL, final URL, redirect count, reasons — not full HTML bodies
Testing
Fixture URLs in CI (use stable test endpoints you control):
- 200 with no redirects
- 301 chain to second domain
- Excessive redirect loop (expect failure)
- 404 broken link
- Blocked internal IP (expect preflight rejection)
Assert policy outputs, not proprietary "risk scores" from undocumented heuristics.
Related reading
| Topic | Article |
|---|---|
| Inspection fundamentals | What Is URL Inspection? |
| Agent validation pipeline | Validate URLs Before AI Agents Open Them |
| Allowlist design | URL Allowlist vs Domain Allowlist for AI Agents |
| Exfiltration defense | URL-Based Data Exfiltration in AI Agents |
Detecting suspicious URLs programmatically means combining parsing, HTTP inspection via the URL Inspector API, redirect analysis, and explicit policy — returning structured reasons your agent runtime and security teams can act on, without overstating what HTTP metadata can prove.
Frequently asked questions
How do I detect suspicious URLs programmatically with IdenticAPI?
Call URL Inspector via RapidAPI: GET https://url-inspector.p.rapidapi.com/inspect?url= with X-RapidAPI-Key and X-RapidAPI-Host headers. Parse status, redirects, final_url, and title; apply tenant policy rules to structured signals.
Does the URL Inspector API return a phishing score?
No. It returns HTTP-level inspection data — status, redirect chain, final URL, metadata. Phishing detection requires additional content and reputation signals not provided by URL-only inspection.
What signals indicate a suspicious URL in policy code?
Common signals include parse failures, disallowed schemes, private or metadata IPs, excessive redirects, final host differing from proposed host, scheme downgrade, and HTTP errors — combined with allowlists and Agent Action Guard.
Should I call URL Inspector from the browser?
No. Call from server-side orchestrators to protect RapidAPI keys and enforce policy before agent fetches.
Can I use inspection results as Agent Action Guard context?
Yes. Include final_url, redirect count, and policy reason codes in the context string when submitting tool proposals for allow, review, or block evaluation.
Related reading
- What Is URL Inspection?
URL inspection parses, normalizes, and analyzes destinations — status codes, redirects, and metadata — for link health a…
- Phishing Detection API: What Developers Need
Evaluate phishing detection APIs — URL analysis, content signals, false positives, latency, and integration without over…
- How to Validate URLs Before an AI Agent Opens Them
Validate URLs before AI agents fetch or open them — protocol restrictions, domain allowlists, redirect handling, and int…