Bulk URL Status & SSL Checker: Redirects & Expiry avatar

Bulk URL Status & SSL Checker: Redirects & Expiry

Pricing

from $0.75 / 1,000 urls

Go to Apify Store
Bulk URL Status & SSL Checker: Redirects & Expiry

Bulk URL Status & SSL Checker: Redirects & Expiry

Check thousands of URLs at once: final HTTP status, full redirect chain, response time, HTTPS, security headers, and SSL certificate issuer, expiry date and days left. Find broken links, bad redirects and expiring certificates.

Pricing

from $0.75 / 1,000 urls

Rating

0.0

(0)

Developer

Red Fox Scout

Red Fox Scout

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

Check thousands of URLs in one run and catch SSL certificates that are expiring or already expired before a site goes down. Turn on Only problem URLs and each run returns just what needs attention: broken pages (4xx/5xx), redirect loops, invalid or expired certificates, and certificates expiring within the days you set. Turn on Check the links on each page and it works as a broken link checker: one row per link, with its source page, anchor text and status.

For every URL you also get the final HTTP status, the full redirect chain, response time, the server, which security headers are present or missing, and the SSL certificate: issuer, expiry date, days left, and whether it's trusted. For SEO teams, site reliability engineers and agencies managing many domains.

Price: $1.00 per 1,000 URLs checked (links too). URLs that can't be reached at all (DNS failure, timeout) are free. A 404, a 500 or an expired certificate is a result, so it's counted. Apify's free plan ($5 monthly credit) covers about 5,000 URLs a month.

SSL certificates expiring in the next 30 days: real output preview (Only problem URLs: certificates expired or expiring within 30 days)

Questions it answers

  • Which of our domains have SSL certificates expiring in the next 30 days, or already expired?
  • Which links on our pages are broken (404/410/500) or redirect somewhere unexpected?
  • Do old URLs 301-redirect to the right new pages after a migration?
  • Which sites redirect in a loop, or send a visitor through too many redirects?
  • Which sites are missing HSTS or a Content-Security-Policy header?
  • Which sites answer slowly?

Who uses this

  • 🔍 SEO teams: find broken pages, redirect chains and links that 404 before search engines do.
  • 🛠️ Site reliability engineers: watch certificate expiry and status codes across every domain you run.
  • 🏢 Agencies: check all client sites in one scheduled run.
  • 🚚 Site migrations: confirm every old URL redirects where it should.

Why this URL Status & SSL Checker

  • 🔒 SSL expiry watch: days left on every certificate; Only problem URLs returns just what needs action.
  • 🔗 Broken link checker: every link on a page with its source page, anchor text and status.
  • 🔁 Full redirect chains: every hop with its status; loops and too many redirects are flagged.
  • ⏱️ Speed and headers: response time, a slow-page flag, the server and which security headers are missing.
  • 🔔 Change alerts: status, redirect and certificate changes since the last run.
  • 💰 $1 per 1,000 URLs, unreachable URLs are free.

How to use the URL Status & SSL Checker

  1. Click Try for free (a free Apify account is enough).
  2. Paste URLs or domains, one per line.
  3. Optional: turn on Only problem URLs in the results, set SSL expires within (days), or turn on Check the links on each page.
  4. Click Start, or schedule it daily, then download the results or send them to Slack, Google Sheets or a webhook.

Input

FieldDefaultWhat it does
urls–URLs or bare domains, one per line. In link mode, the pages to read links from.
startUrls–Same as urls, in Apify's standard start-URL format.
datasetId–Check the websites in another Actor's dataset (see below).
datasetUrlFieldwebsiteThe dataset field with the website. Dot paths like contact.website work.
maxDatasetItems10000Read at most this many rows from that dataset.
monitorName–Change alert name. Compares each run with the previous run of the same name.
onlyChangesfalseNeeds a change alert name. Keep only new and changed sites in the results.
sslExpiringWithinDays30Certificates expiring within this many days get a problem. 0 flags only expired ones.
onlyProblemsfalseKeep only URLs with a problem (see SSL expiry watch). The other URLs are free.
checkLinksOnPagefalseCheck every link on each URL (broken link checker). One row per link.
checkExternalLinkstrueLinks on each page: also check links to other sites.
checkAssetsfalseLinks on each page: also check images, scripts, stylesheets and iframes.
maxLinksPerPage100Links on each page: check at most this many unique links per page. The rest are not checked or charged.
methodGETGET reads each response as a browser does. HEAD is faster: headers only, and a URL that refuses HEAD is retried with GET.
followRedirectstrueFollow redirects to the final page. Off: report only the first response.
maxRedirects10Stop after this many redirects. A URL still redirecting then gets Too many redirects.
userAgentChromeThe browser identity sent with each request. Empty uses a current Chrome string.
slowThresholdMs2000A response slower than this gets isSlow: true.
maxConcurrency20URLs (or pages in link mode) checked in parallel.
requestTimeoutSecs30Give up on a URL after this long.
proxyConfigurationoffTurn on if some sites block or rate-limit the checks. Uses your own Apify Proxy.

Example input for the SSL expiry watch:

{ "urls": ["https://expired.badssl.com", "https://self-signed.badssl.com", "https://github.com", "https://apify.com"], "sslExpiringWithinDays": 30, "onlyProblems": true }

Output

One row per URL, or one row per link in link mode. The real row for http://github.com from a run with the default options, shortened:

{
"inputUrl": "http://github.com",
"url": "https://github.com/",
"domain": "github.com",
"httpStatus": 200,
"finalStatus": 200,
"redirects": 1,
"redirectChain": [{"url": "http://github.com/", "status": 301}, {"url": "https://github.com/", "status": 200}],
"responseTimeMs": 133,
"https": true,
"server": "github.com",
"securityHeadersPresent": ["strict-transport-security", "content-security-policy", "x-frame-options", "x-content-type-options", "referrer-policy"],
"securityHeadersMissing": ["permissions-policy"],
"sslValid": true,
"sslError": null,
"sslIssuer": "Sectigo Limited",
"sslSubject": "github.com",
"sslValidFrom": "2026-09-01T00:00:00.000Z",
"sslValidTo": "2026-11-29T23:59:59.000Z",
"sslDaysLeft": 52,
"sslAltNames": ["github.com", "www.github.com"],
"tlsProtocol": "TLSv1.3",
"status": 200,
"finalUrl": "https://github.com/",
"statusText": "OK",
"isBroken": false,
"isRedirect": true,
"redirectCount": 1,
"contentType": "text/html; charset=utf-8",
"contentLength": null,
"isSlow": false,
"problem": null,
"error": null,
"checkedAt": "2026-10-08T12:53:06.422Z"
}

status and finalUrl repeat finalStatus and url under the names other tools expect. contentLength is empty when the server does not send a Content-Length header, which is common for compressed or streamed pages.

A site whose certificate a browser would reject (expired, self-signed, wrong host) still gets a full row: sslValid: false, the reason in sslError (e.g. CERT_HAS_EXPIRED), the expiry date and negative sslDaysLeft. The HTTP status stays empty, because the page isn't loaded over an untrusted connection. isBroken is true for such a row.

Example tasks

Ready-made inputs you can open, change and run:

SSL expiry watch

Set SSL expires within (days) (default 30) and turn on Only problem URLs in the results. Each run then returns only the URLs that need attention, and the problem field says why:

  • SSL expires in 12 days or SSL expires today
  • SSL expired 3 days ago
  • SSL invalid: DEPTH_ZERO_SELF_SIGNED_CERT (any certificate a browser would not trust, e.g. a name mismatch)
  • HTTP 404, HTTP 503 and other 4xx/5xx answers
  • Redirect loop, Too many redirects
  • Unreachable (free; always kept)

Put it on an Apify schedule and the dataset of each run is that day's list. You pay only for the URLs in that list: healthy URLs are checked but free. The problem field itself is not part of change alerts, so the reason can change from day to day without triggering one.

Example from a real run (problem values from three URLs in one run):

{ "inputUrl": "https://expired.badssl.com", "sslValid": false, "sslError": "CERT_HAS_EXPIRED", "sslDaysLeft": -4197, "problem": "SSL expired 4197 days ago" }
{ "inputUrl": "https://self-signed.badssl.com", "sslValid": false, "sslError": "DEPTH_ZERO_SELF_SIGNED_CERT", "sslDaysLeft": 728, "problem": "SSL invalid: DEPTH_ZERO_SELF_SIGNED_CERT" }
{ "inputUrl": "https://httpbin.org/status/404", "finalStatus": 404, "isBroken": true, "problem": "HTTP 404" }

Turn on Check the links on each page and list the page URLs (one or two pages is typical). The Actor reads the links in each page's HTML and checks every one. You get one row per link:

  • sourceUrl: the page the link is on
  • anchorText: the link text, or the image alt text
  • linkType: internal (same site) or external
  • linkTag: the element it came from: a, img, script, link or iframe
  • url: the link as written on the page; finalUrl after any redirects; status, isBroken, problem

Options: Include links to other sites (on), Include images, scripts and stylesheets (off), and Max links per page (100). A link that appears twice on a page is checked once. mailto:, tel:, javascript: and #anchor links are skipped. A page that can't be loaded, or isn't HTML, gives one free row. Real row from a run on a Wikipedia article (shortened):

{
"inputUrl": "https://en.wikipedia.org/wiki/Link_rot",
"url": "https://doi.org/10.1002%2Fasi.20159",
"domain": "doi.org",
"httpStatus": 403,
"finalStatus": 403,
"status": 403,
"statusText": "Forbidden",
"redirects": 1,
"isRedirect": true,
"isBroken": true,
"responseTimeMs": 536,
"contentType": "text/html; charset=UTF-8",
"problem": "HTTP 403",
"sourceUrl": "https://en.wikipedia.org/wiki/Link_rot",
"anchorText": "10.1002/asi.20159",
"linkType": "external",
"linkTag": "a",
"error": null
}

Check websites from another Actor (Google Maps leads, lead lists)

Have a list from Google Maps Scraper or any other Actor? Pick its dataset under Websites from another Actor. This Actor reads the website field (or the field you name, e.g. url, domain or contact.website) and checks every site. No copy and paste.

To run it automatically after every scrape, add an Actor-to-Actor integration to the source Actor or task with this input:

{ "datasetId": "{{resource.defaultDatasetId}}", "datasetUrlField": "website" }

Change alerts

Give the run a Change alert name (e.g. clients-weekly) and put it on an Apify schedule. Each row then gets changeStatus (new, changed or unchanged) and changedFields, compared with the previous run of the same name, so you see when a status code, redirect chain, certificate or security header changes. Turn on Only new and changed sites and each run's dataset is just the change report; unchanged sites are still checked and charged as usual. Add Apify's Slack or email integration to get the report delivered. Change alerts work on page checks, not on links-on-page mode.

Notes

  • Up to 10 redirects are followed (change it with Max redirects). A redirect back to a URL already seen is reported as a redirect loop.
  • The status is what the server returns to this check. Some sites answer bots differently, so a 403 can mean "blocked" rather than "down".
  • Certificate data comes from a standard TLS handshake with the final host.

What this Actor does not do

  • No logins, cookies or shared accounts, no CAPTCHA solving, and no pages behind a sign-in.
  • No browser: links that only appear after a page's JavaScript runs are not found in links-on-page mode.
  • It checks the URLs and pages you give it. It does not crawl a whole site by itself; feed it a sitemap's URL list or a crawler's output instead.
  • No personal data: it reads public pages and public certificates only.

How much does it cost?

  • URL checked: $0.001 per URL that answers ($1.00 per 1,000), including 4xx/5xx and certificate errors.
  • Link checked (links on each page): $0.001 per link that answers, the same rate.
  • Only problem URLs: URLs left out of the results are free. You pay only for the problems you get.
  • URLs that can't be reached at all (DNS failure, timeout), and pages that can't be read: free.
  • Actor start: $0.00005 per GB of memory (default 1 GB = $0.00005 per run).
URLsCost
100about $0.10
1,000about $1
10,000about $10

Apify's free plan includes $5 of credit every month, enough for about 5,000 URLs. Paid Apify plans get Store discounts of up to 25%. You can set a maximum cost per run; the Actor stops cleanly when it's reached.

FAQ

Is this legal? It makes one normal request to each URL or link you list, or to each page you give for link checks, and reads the public certificate, like a browser does. No personal data is collected.

Why is a URL I know works marked 403? Some sites block automated visitors. The status shown is what the server returned to this check.

Can I check certificates every day? Yes. Set Only problem URLs and a change alert name, then put the Actor on an Apify schedule. Each run's dataset is that day's list of expiring or broken URLs.

Why do URLs I filter out still cost money? Each URL has to be checked to know whether it has a problem, and checking is what costs. Filtering only decides what is saved.