Redirect Map & URL Status Checker
Pricing
$1.00 / 1,000 checked urls
Redirect Map & URL Status Checker
Check small public URL lists and migration mappings with ordered HTTP hop evidence, conservative target verdicts and explicit limits.
Pricing
$1.00 / 1,000 checked urls
Rating
0.0
(0)
Developer
Roman V
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
2
Monthly active users
4 days ago
Last modified
Categories
Share
Check a small public URL list or verify where migration redirects actually end. Supply an optional expected destination for each input. The dataset contains one evidence row per checked input, in input order, including duplicates.
Each row records the observed HTTP responses, raw accepted Location values, resolved redirect targets, terminal status and a conservative expected-target verdict. A loop, an exhausted hop allowance, an HTTP error and a failed connection have different outcomes.
First run
Run with {} or no input to check https://example.com/ once. An explicit {"mappings": []} checks nothing and produces an EMPTY summary.
{"mappings": [{"url": "https://example.com/", "expectedUrl": "https://example.com/"}]}
For status-only checks, omit expectedUrl:
{"mappings": [{"url": "https://example.com/"}]}
Replace these demonstration URLs with public URLs you are authorized to check. For a migration, each object can contain the old URL and its expected final URL. Both modes share one input format and one dataset.
Results
| Field | Meaning |
|---|---|
inputIndex, inputUrl | Original zero-based position and supplied source URL. Duplicates are checked separately. |
hops | Ordered responses, each containing url, status, accepted raw location and resolvedTarget. |
terminalUrl, terminalStatus | Populated only after a non-redirect HTTP response. A stopped chain has no invented terminal URL. |
lastObservedUrl, lastObservedStatus | Last HTTP response actually returned by the HTTP client, including a stopped redirect. |
outcome, reason | Stable result and any more specific failure or limit reason. |
targetMatch | True/false only for a terminal 2xx response with an expected URL. Otherwise null. |
temporaryRedirects, permanentRedirects | Observed 302/303/307 and 301/308 responses. These are HTTP classifications, not SEO scores. |
fetchAttempts, httpResponses | Transport invocations and returned HTTP responses. DNS failures count as attempts; an attempt is not proof a GET reached the server. |
MATCH and TARGET_MISMATCH apply to expected destinations. CHECKED means a status-only check reached a 2xx response. HTTP_ERROR preserves 4xx/5xx responses. HTTP_OTHER covers other terminal HTTP statuses. A 404 at the expected URL is an HTTP error with an unknown match, never a successful migration.
LOOP means a normalized network URL repeated. HOP_LIMIT means the next redirect would exceed maxHops. REDIRECT_INVALID covers missing, duplicate or malformed Location values. UNSAFE_REDIRECT stops an explicitly forbidden target. A hostname that resolves to a private address returns FETCH_FAILED with DNS_UNSAFE_ADDRESS. No private connection is attempted.
Download JSON or CSV from the dataset. JSON preserves nested hop objects most directly. OUTPUT in the default key-value store contains one compact receipt per accepted input, counts, limits and delivery/billing status. It does not duplicate full paid hop evidence.
COMPLETE means the accepted inputs were processed within the collection budget. It does not mean every URL is healthy or every migration matches. PARTIAL means some checks could not finish or were excluded by a limit. All transport failures produce FAILED; invalid input produces a failed run before source access. EMPTY is an intentional zero-input result.
Comparison rules and supported URLs
Comparison lowercases the scheme and hostname, removes the default port, treats an empty path as /, and ignores fragments. It preserves path case, trailing slashes, query values and ordering, and percent-encoded path/query bytes. It does not follow the expected URL separately or infer equivalence from page content. A different encoding can therefore be reported as a mismatch even when an origin serves identical content.
Inputs must use ASCII URLs, with non-ASCII characters percent-encoded and international hostnames written as punycode. Only HTTP port 80 and HTTPS port 443 are supported. Userinfo, sensitive query-key names, non-public IP addresses, local hostnames, trailing-dot hosts, IPv6 zone/transition forms and explicit empty query delimiters such as /page? are rejected. Invalid input rejects the whole batch; nothing is silently dropped. Some additional source-side restrictions can still prevent access.
Relative and scheme-relative redirects are resolved against the current URL. Fragments do not create an extra network request. Unsafe or sensitive Location values are withheld from evidence rather than copied into output. Ordinary accepted Location values remain unchanged.
Limits
| Setting | Default | Allowed range |
|---|---|---|
maxUrls | 100 | 1 to 100 |
maxHops | 5 | 0 to 10 |
maxRequests | 300 | 0 to 1,100 |
requestTimeoutSecs | 10 | 1 to 20 |
maxDurationSecs | 60 | 1 to 120 |
Requests are serial with no retries. Each checked input can use at most maxHops + 1 fetch attempts. The run-wide request and source-duration budgets also apply. Inputs excluded before their first attempt get NOT_CHECKED receipts in OUTPUT and no dataset row. A chain stopped after work began keeps its partial evidence row with REQUEST_LIMIT or TIME_LIMIT.
The dataset payload is capped at 8 MiB per run. The client limits header fields to 4,096 bytes, header count to 64, retained aggregate headers to 64 KiB, and raw bytes admitted to the HTTP parser to 256 KiB per attempt. Response bodies are not extracted or decompressed. A GET can receive bounded body data before headers reach the application; malformed body framing or an oversized early read can cause FETCH_FAILED. These are application/parser limits, not a claim of zero body bytes on the network or a total bandwidth invoice. HTTP payload corruption is not audited.
Public DNS answers are checked before connection and numeric addresses are pinned into the connector. Redirects repeat the checks. TLS certificate and hostname verification remain enabled. Environment proxies, .netrc, cookies and login are disabled. There is no crawling, JavaScript rendering, page-text extraction, proxy bypass, SEO scoring, persistent monitoring or notification feature.
Billing and delivery
The price is $0.001 per delivered checked-input row, charged through Apify's automatic dataset-item event. This includes rows showing HTTP errors, failed connections, loops, invalid redirects and partial-chain evidence, as well as successful checks. Inputs marked NOT_CHECKED without a dataset row do not incur a row charge. There is no start fee, report fee or separate usage surcharge.
Set a positive maxTotalChargeUsd to limit row charges. A $0.0015 cap allows at most one row; $0.0025 allows at most two rows; and 100 rows cost at most $0.10. The runtime checks the remaining budget before source work and uses decimal arithmetic for fractional caps. Do not use maxTotalChargeUsd=0 as a dry-run switch: in hosted API testing, the platform treated zero as an unset cap. Smaller positive caps may be rejected by the platform. To make no checks, use the explicit empty input described above. The runtime requires a single automatic dataset-item event and rejects additional priced events. Billing is based on delivered evidence, not on whether the checked URL is healthy or matches an expected destination.
The runtime journals collection and delivery. Dataset POST retries and automatic redirects are disabled in the pinned SDK adapter. A confirmed push preserves its delivered and charged counts if later bookkeeping fails. An ambiguous write reports unknown counts and a failed run. It is never automatically retried. Completed restart state replays the receipt without fetching or pushing; incomplete or conflicting state fails before source work. Leave automatic restart off for hosted QA and production until hosted restart behavior is independently accepted.
Local development
Requires Python 3.12. Use 256 MB of Actor memory. Dependencies, including transitive versions, are pinned in requirements.txt.
python3.12 -m venv .venv.venv/bin/python -m pip install --only-binary=:all: -r requirements.txt.venv/bin/python -I -B run_tests.py.venv/bin/python -m src
Local tests use synthetic source fixtures. Before checking production URLs, review the input limits, set an explicit positive charge cap and keep automatic restart off.