Link Route Audit — Bulk HTTP Status & Redirects
Pricing
from $2.25 / 1,000 http url results
Link Route Audit — Bulk HTTP Status & Redirects
Check a list of public URLs before a site move or SEO review. See final HTTP status, ordered redirect destinations and broken-link flags, then export a table. Up to 100 input URLs per run.
Pricing
from $2.25 / 1,000 http url results
Rating
0.0
(0)
Developer
Cliqto Media
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Check a list of public URLs before a site move or SEO review. This bulk URL status checker returns the final HTTP status, redirect destinations and broken-link flags for each processed URL. Start with one URL and open its result table. Each run accepts up to 100 input items. An empty list fails; a stopped run may return part of the list. The charge model is pay per useful HTTP result plus an Actor Start event and platform usage. Optional Apify Proxy traffic adds usage costs.
Table of contents
- What it checks
- Data you get
- Quick start
- Input reference
- Input examples
- Real output example
- Output field reference
- Run summary and storage
- Pricing and cost controls
- Use cases
- Scheduling and monitoring
- API and integrations
- Export to JSON CSV and Excel
- Limits and partial results
- Troubleshooting
- FAQ
- Related tools
- Support and privacy
What it checks
The Actor sends HTTP requests to the URLs you supply. It starts with HEAD and uses GET when the server returns 405 or 501 for HEAD. It does not read page content. It follows safe redirect destinations and returns one row per processed unique URL.
Use it for a known list from a migration plan, link report or QA check. It does not crawl a website, find URLs, render JavaScript, log in, or check page text. A 200 response alone does not prove that a page has the right content or is indexed.
Data you get
Each Dataset row has nine fields. Use statusCode to see the final HTTP response, isBroken to find failures, and redirectChain with finalUrl to review the route.
| Result | Meaning | Next step |
|---|---|---|
200, not broken | The final server returned success | Check whether finalUrl is the address you expect |
404, broken | The server answered “Not Found” | Fix the URL or redirect |
0, broken, finalUrl: null | The check ended without a usable HTTP response | Review DNS, connection, TLS, timeout or access |
Redirect to 404 | A route exists but ends at a missing page | Fix the destination |
This is a point-in-time HTTP check. Server rules, location and connection mode can change the result. There is no saved snapshot comparison or automatic change alert.
Quick start
- Open the Actor in Apify Console and choose Input.
- Switch to JSON and paste the minimal input below, or enter the URL objects in URLs to check.
- Keep direct requests for a first check. A fresh form offers one public example.com URL; you can start this sample without editing it. API calls still require startUrls and never substitute a hidden demo.
- Click Start. A run uses the selected build and run options.
- Open Output → URL results → Table. Check
statusCodeandfinalUrl. - Choose Export to save the results. Open Storage to read the separate summary.
The example checks a public test service with a 301 redirect to a 200 response. Site behavior may change. You can replace it with a public URL you control.
Input reference
| Key | Form title | Type and shape | Required | Runtime default / form prefill | Range or choice | Effect and advice |
|---|---|---|---|---|---|---|
startUrls | URLs to check | Array of objects with a string url | Yes | No runtime default; UI prefill [{"url":"https://example.com"}] | 1–100 items; each URL up to 4,096 characters | Supply full public http:// or https:// URLs. List size is checked before duplicate removal. |
maxConcurrency | URLs checked at once | Integer | No | 20 / 20 | 1–100 | Number of URL checks at once. Start with 2–3 for slow sites. The API form range is enforced by schema; runtime clamps finite numeric values to the range. |
proxyConfiguration | Connection mode | Object | No | {"useApifyProxy":false} / No proxy | useApifyProxy boolean; optional string-array groups and string countryCode | Direct is the default. Choose available Apify Proxy groups/location only when needed; access and extra costs depend on your account. Custom proxy URLs and credentials are rejected. |
requestTimeoutSecs | Request timeout (seconds) | Integer | No | 10 / 10 | 1–30 | Maximum wait for each DNS, proxy CONNECT and response-header phase. It is not a total per-URL time limit. |
A URL object has the form {"url":"https://example.com/"}. Strings alone are not accepted. Leading and trailing spaces are removed. Duplicate detection uses the parsed URL; query strings are kept. Invalid items are skipped and listed in failedInputs. If none remain valid, the run fails.
| Settings used together | Result | Cost or safety note |
|---|---|---|
| More parallel checks + slow or rejecting servers | More active requests; possible retries or rate limits | Higher concurrency does not ensure a faster run |
| Proxy enabled + redirect/retry | Each request uses the selected connection mode | Extra traffic can add cost |
| Short phase timeout + several hops/retries | A check can still take longer than one phase timeout | Use the run timeout as a separate bound |
TLS certificate checks are always on. ignoreTlsErrors is unsupported. Headers, cookies, login details and a custom proxy URL are not input options.
Input examples
Minimal check
{"startUrls": [{"url": "https://httpbingo.org/redirect-to?url=%2Fstatus%2F200&status_code=301"}]}
Expected: a row with statusCode: 200, isRedirect: true, and redirectChain: ["https://httpbingo.org/status/200"]. This same URL was checked in the recorded run shown below; that run also contained other URLs.
Small SEO review
{"startUrls": [{"url": "https://httpbingo.org/status/200?case=tz06-200"},{"url": "https://httpbun.com/status/404?case=tz06-404"},{"url": "https://httpbingo.org/redirect-to?url=%2Fstatus%2F200&status_code=301"}],"maxConcurrency": 2,"proxyConfiguration": {"useApifyProxy": false},"requestTimeoutSecs": 10}
Expected: a 200 row, a 404 row and a redirected 200 row, if the test services keep these responses. These URLs are part of the same measured corpus. Use a small concurrency value for your first real list. To use Apify Proxy, change only useApifyProxy to true and choose a group you can access.
Real output example
This is one full Dataset item from a real Cloud run on 2026-10-02. It is selected from eight results; timing and date are observed values, not fixed expectations.
{"url": "https://httpbingo.org/redirect-to?url=%2Fstatus%2F200&status_code=301","statusCode": 200,"statusMessage": "OK","isBroken": false,"isRedirect": true,"redirectChain": ["https://httpbingo.org/status/200"],"finalUrl": "https://httpbingo.org/status/200","responseTime": 122,"checkedAt": "2026-10-02T14:18:28.271Z"}
The chain lists destinations in order and includes the final URL. It does not repeat the input URL as the first hop. The array contains URLs, not objects with a status code for each hop.
Output field reference
All nine keys are present on each result row. They are result fields, not input controls.
| Key | Table title | Type / empty value | Meaning and example |
|---|---|---|---|
url | Original URL | String; not null | The submitted URL after spaces are removed; the example input URL |
statusCode | HTTP status code | Integer; not null | Final HTTP code such as 200 or 404; 0 for a technical failure without a usable final response |
statusMessage | Status message | String; not null | HTTP message such as OK, or a safe diagnostic such as Network request failed; low-level error details are not stored |
isBroken | Is broken | Boolean | True for status 0, HTTP codes at least 400, blocked targets, redirect loops or the hop limit |
isRedirect | Is redirect | Boolean | True if a redirect was seen; it can stay true when the next target is blocked |
redirectChain | Redirect chain | Array of strings; [] when no safe destination was added | Safe destinations in order, including the final destination; unsafe targets are excluded |
finalUrl | Final URL | String or null | Last URL checked on a normal HTTP path. Null on a technical failure. On a redirect stop, review the broken flag and message; this is not proof of a successful arrival. |
responseTime | Response time ms | Integer milliseconds; not null | Time for the URL check, including hops, phase waits, retries and retry delays; not a browser page-load metric |
checkedAt | Checked at | String; UTC ISO date/time | Time when the URL check started, such as 2026-10-02T14:18:28.271Z; use it with the result time |
The Actor does not return redirectCount, contentType, contentLength, server, page text, canonical tags or headers. To count stored safe destinations in your own code, use the array length; it need not equal every redirect seen when a target was blocked.
Run summary and storage
Dataset stores the URL rows. The Actor’s output schema provides links to URL results and Run records. Run records opens the Key-value store collection. Select RUN_SUMMARY or OUTPUT there. They are separate from the nine Dataset columns.
OUTPUT has results (the Dataset rows), summary (the terminal summary), and datasetUrl (the Console Dataset link). RUN_SUMMARY holds that same summary. Open the run’s Storage tab, then its Key-value store to read these records.
| Summary key | Type | Meaning |
|---|---|---|
received | Integer | Original number of submitted items |
valid | Integer | Accepted unique URLs before checking |
duplicates | Integer | Repeated accepted URLs skipped |
processed, results | Integer each | Number of result rows written; both use the same count |
domainEmpty | Integer | Always 0; this checker has no domain-empty result |
technicalFailures | Integer | Processed rows with status 0 |
unprocessed | Integer | Valid URLs left without a result row |
attempts | Integer | Request attempts, including DNS/socket failures, hops, retries and HEAD/GET |
fallbacks | Integer | HEAD requests followed by GET |
retries | Integer | Extra request attempts started after a retry decision |
rateLimits | Integer | HTTP 429 responses received |
cancelled | Boolean | Whether the checker received a stop signal |
outcome | String | succeeded, partial or error |
timings.startedAt, timings.finishedAt | UTC ISO strings | Checker start and finish; not the full platform start/pull time |
transport.mode | String | direct or proxy; no proxy address or password |
failedInputs | Array of objects | Rejected entries with integer zero-based index and safe string reason |
Normal reconciliation: received = valid + duplicates + failedInputs.length, valid = processed + unprocessed, and Dataset length equals results. HTTP 404 alone can still have summary succeeded: the check worked and returned an HTTP result. partial covers technical failures, rejected inputs, queued work or cancellation.
Before result publication, a run-level error uses a smaller summary shape: {"outcome":"error","error":{"code":"INVALID_INPUT","message":"..."}}. Standard counters are absent in this shape. OUTPUT.results is empty. Other adapter/storage/runtime errors can also end the run; review its status and log. Do not treat an empty Dataset as proof that every URL is good.
Pricing and cost controls
The applied model is pay per event plus platform usage. A stored URL result with an HTTP response costs USD 0.00225. HTTP 404 and 503 are useful check results and count. Technical failures with status 0, duplicates, invalid inputs, queued URLs and summaries do not count as result events.
The platform charges USD 0.001 for Actor Start at the supported 128–256 MB memory range. This start charge can apply even when input validation fails. Compute, storage and optional proxy use are charged separately at your account rates. Check the Pricing tab before starting.
| Useful HTTP results | Result events + one start | Additional cost |
|---|---|---|
| 1 | USD 0.00325 | Platform usage and optional proxy |
| 10 | USD 0.02350 | Platform usage and optional proxy |
| 100 | USD 0.22600 | Platform usage and optional proxy |
| 1,000 over 10 batches of 100 | USD 2.26000 | Usage of all 10 runs; this is arithmetic, not a single-run capacity claim |
Set a maximum cost per run, timeout and memory in run options. The minimum accepted cost limit is USD 0.00325. Private defaults are 256 MB and 180 seconds. Input concurrency is separate. The Actor limits the checked unique URLs to the number of result events its available event budget can cover; technical failures can leave some of that budget unused. A low budget can produce a partial result and unprocessed URLs. Platform usage can reduce the budget further or stop the run.
Results are saved in a batch, then useful result events are charged once each. A run-local RESULTS_PENDING record keeps the result batch for recovery. If a storage or charging step fails, already stored results remain available and the run can fail. A resumed run checks stored rows and platform event counts before writing or charging again. A hard stop before the batch is saved can still lose results. There is no total-cost discount or guaranteed profit promised to buyers.
Use cases
| Buyer job | Add to startUrls | Review | Next step |
|---|---|---|---|
| Site migration URL check | Your old public URLs | redirectChain, finalUrl, isBroken | Compare the final destination with your own migration map |
| Broken link list | URLs from a link report | statusCode, isBroken, statusMessage | Fix or replace failing links |
| QA after a release | Known public endpoints | statusCode, responseTime, checkedAt | Re-check failed endpoints and keep the dated export |
| Redirect audit | Known redirecting URLs | Ordered redirectChain, isRedirect | Review extra hops or broken destinations |
The Actor does not import a sitemap or compare an old-to-new map for you. It checks the list you provide.
Scheduling and monitoring
To repeat a known list, save the input as an Apify task, then create a schedule for that task in Console. Choose a small list, a time and run limits. Every scheduled run can incur usage costs.
Keep dated exports if you need to compare runs. There is no built-in snapshot diff, uptime SLA or automatic change alert. Scheduling does not add those features. This guide does not create a schedule for you. See the Apify scheduling guide.
API and integrations
Use the private Actor ID from your own authorized Apify account. Set APIFY_TOKEN in your environment; never place it in a URL or commit it. Save the input as input.json.
curl --fail-with-body --silent --show-error \--request POST \--header "Authorization: Bearer ${APIFY_TOKEN:?Set APIFY_TOKEN locally}" \--header 'Content-Type: application/json' \--data-binary @input.json \'https://api.apify.com/v2/acts/NmhMbSI7fgkagucYf/runs?build=0.1.10&memory=256&timeout=180&maxTotalChargeUsd=0.05'
This starts a paid run; it does not wait for completion. Read the returned data.id with GET /v2/actor-runs/{runId} until the run ends. Then read GET /v2/datasets/{defaultDatasetId}/items for the rows and the run’s Key-value store records for the summary. Keep the same Bearer header. Supply an exact available build from your Actor; newer builds may replace the example version.
Use statusCode or isBroken in your next system, and pass finalUrl only after checking the result. The Apify API reference explains run and storage requests. Apify’s SDK/client can perform the same steps. This Actor has no custom MCP server or verified MCP tool; it does not need a new service installation.
Export to JSON CSV and Excel
- Open a completed run’s Output → URL results.
- Select Table to scan the rows, or JSON to view field names and values.
- Click Export and choose JSON, CSV or Excel (XLSX).
- Keep all nine columns when another tool needs the full result. Array and null display can differ across export formats; use JSON to preserve these types.
- Download
RUN_SUMMARYseparately from Storage when you also need rejected or unprocessed counts.
Exports read the stored results; you do not need to start another run for each format. See Dataset storage and export.
Limits and partial results
- At most 100 input items per run, counted before duplicate removal. Split larger lists yourself.
- Concurrency range 1–100, default 20. Actual Cloud capacity was checked at concurrency 3 with 100 simple HTTP results; this does not promise the same speed or success for all sites.
- Up to 10 redirect hops; loops and the hop limit produce broken results. A final target can be present in the chain before the cap prevents fetching it.
- Up to 2 extra retries per request for network failures, 429 or 5xx. HEAD→GET fallback adds a request. Requests can therefore exceed the number of URLs.
- Request phase timeout 1–30 seconds, default 10. Several phases, hops and retries can take longer than one timeout value.
- Only public HTTP/HTTPS destinations. Private-network, loopback and unsafe targets are blocked, including at redirects and retries. TLS verification stays on.
- URL credentials, secret query values and fragments are rejected. Custom proxy credentials are not accepted.
- Results are saved as a batch after checking. A graceful stop can save finished and active rows and count queued URLs in
unprocessed; a hard platform kill or storage failure may lose final results. There is no streaming or resume guarantee. - A status 0, 403, 429 or blocked result does not prove the page is absent. It reports the response or failure seen by this run.
Troubleshooting
| Symptom | Possible reason | Check | Action |
|---|---|---|---|
| Input form says “This field is required” | Empty URL list | startUrls object array | Add at least one full public URL |
FAILED with INVALID_INPUT | Missing/empty/too-large list, unsupported option, or no valid URLs | Error summary and input shape | Correct the input; do not add secrets |
| Status 0 with null final URL | DNS, TLS, connection failure, timeout or blocked target | statusMessage, failed inputs and logs | Verify a public URL and retry a small subset |
| HTTP 404 | Server returned Not Found | Submitted and final URLs | Correct the URL or redirect |
| Fewer rows than input items | Duplicates, rejected entries, or queued work | duplicates, failedInputs, unprocessed | Fix the input or split a list |
| Succeeded but PARTIAL | Some checks failed technically or input was rejected | Summary, status0 rows | Review the failed subset; a platform success is not proof all URLs are good |
| Many 429/slow checks | Server rate limits or slow response | rateLimits, attempts, retries | Reduce concurrency and wait before a small re-check |
| Run stopped before results appeared | Batch saving and hard stop | Terminal status, summary/storage presence | Use smaller lists and enough run time; do not assume saved rows |
Log events use numeric counts and safe event names. They do not contain raw proxy addresses or detailed low-level errors.
FAQ
Does it detect soft 404 pages?
No. It does not read page content. A page can return 200 while showing an error message.
Can I see the status of every redirect hop?
The Dataset stores destination URLs, not a status code for each hop. statusCode is the final HTTP code, or 0 on technical failure.
Is a redirect always broken?
No. A redirect to 200 normally has isRedirect: true and isBroken: false. A redirect to 404 is broken.
Is the response time a speed score?
No. It is the whole URL check time from the run environment, including retries and waits. It is not a Core Web Vital.
Can I use login pages or internal addresses?
Public login page addresses can return an HTTP status, but the Actor does not sign in. Private or internal destinations are blocked.
Does a schedule compare results for me?
No. Export the dated rows and compare them in your own system.
Related tools
Use your spreadsheet or migration map with this Actor’s exported finalUrl and statusCode fields. No extra product is required.
Support and privacy
For a bug or question, use the developer contact or Issues route shown on the Actor page in Apify. Include the run ID, list size, connection mode and a safe description of the problem. Do not send tokens, cookies, proxy passwords or a private URL list. Use the Apify help center for account or platform support.
Do not submit secrets in URL paths, query values or other input. Apify keeps the original INPUT record; this Actor cannot remove secrets you already submitted. Public URLs and final destinations are stored in Dataset/OUTPUT. Share exports only when the URLs are safe to share.
Checks access only public targets. This Actor is independent and is not affiliated with the websites it checks. It does not certify site ownership, content, access rights, availability or SEO ranking. Review the actual HTTP result and the limits above before acting on it.