GitHub Pages Custom Domain Go-Live and Dangling-Domain Watch avatar

GitHub Pages Custom Domain Go-Live and Dangling-Domain Watch

Pricing

from $5.00 / 1,000 run starteds

Go to Apify Store
GitHub Pages Custom Domain Go-Live and Dangling-Domain Watch

GitHub Pages Custom Domain Go-Live and Dangling-Domain Watch

Checks GitHub Pages sites on custom domains: DNS records for the apex and www, HTTPS status of each required path, the HTTP-to-HTTPS redirect, the certificate host name, dangling-domain risk, and the Pages API state when a token is given. Gives PASS, WARN

Pricing

from $5.00 / 1,000 run starteds

Rating

0.0

(0)

Developer

kingii98

kingii98

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

12 days ago

Last modified

Categories

Share

This Actor checks GitHub Pages sites on custom domains. For each domain it tells you:

  • when DNS stops pointing at GitHub Pages,
  • when HTTPS or the HTTP-to-HTTPS redirect breaks,
  • when the certificate does not match the domain name,
  • when the domain still points at GitHub Pages but no site serves it (dangling-domain risk). Another GitHub user can then claim the domain for their own site.

It gives each domain a verdict: PASS, WARN or FAIL. It keeps the last verdict of each domain, and it sends one alert for each verdict change. A site that stays broken does not send one alert for each run.

Use it when you run several GitHub Pages sites on custom domains, for example as an agency, an open-source maintainer or a documentation team.

The Actor is HTTP only. It uses DNS-over-HTTPS queries to free public resolvers and plain HTTP and HTTPS requests. It uses no browser, no proxy and no database.

When to run it

  • On an Apify schedule, for example once each day. The Actor sends an alert only when a verdict changes.
  • From a Pages deploy workflow, after each publish. Read gate_pass from the summary record.

How it works

For each domain, the Actor does these steps:

  1. It asks Google Public DNS (and Cloudflare when Google does not answer) for the A and AAAA records of the domain and of its www or apex partner. Each answer includes the CNAME chain. It marks each record that is not a documented GitHub Pages target.
  2. It sends GET http://<domain>/ and follows redirects until the first HTTPS URL. http_to_https is true when HTTP redirects to HTTPS on the domain or its partner.
  3. It sends GET https://<domain><path> for the root path and each required path, and follows at most 3 redirects. A path passes on HTTP 2xx.
  4. It reads the certificate result of the HTTPS request for the root path.
  5. It looks for the GitHub Pages "site not found" page in the HTTP and HTTPS answers.
  6. When you give github_token and the domain has a repo, it reads the GitHub Pages API state of the repository.
  7. It gives the verdict, compares it with the stored verdict, and sends one alert when the verdict changed.

At the end it writes one summary record with the gate result, and it writes the new verdicts to the state record.

GitHub Pages targets

These targets were confirmed with a probe on 2026-09-15:

Record typeGitHub Pages target
A185.199.108.153, 185.199.109.153, 185.199.110.153, 185.199.111.153
AAAA2606:50c0:8000::153, 2606:50c0:8001::153, 2606:50c0:8002::153, 2606:50c0:8003::153
CNAMEa host name that ends in .github.io

The "site not found" page is an HTTP 404 with the text There isn't a GitHub Pages site here. or the title Site not found · GitHub Pages.

The www or apex partner

  • For www.example.com, the partner is example.com.
  • For example.com and example.co.uk, the partner is www.example.com and www.example.co.uk.
  • A deeper subdomain, for example docs.example.com, has no partner.

A partner that does not exist is correct. A partner that exists and has a record that is not a GitHub Pages target gives a warning.

Input

FieldRequiredDefaultDescription
domainsYeschoosealicense.com and semver.org1 to 100 items.
domains[].domainYesnoneA custom domain of a GitHub Pages site, for example docs.example.com.
domains[].repoNononeThe repository in the form owner/name. The Actor uses it only for the Pages API state.
domains[].required_pathsNo["/"]0 to 5 paths that start with /. The root path / is always checked.
github_tokenNononeA token with Pages read access. The Actor sends it only to api.github.com. It is a secret input field.
alert_webhook_urlNoemptyOne public HTTPS URL. The Actor sends one JSON POST for each verdict change.

Example input:

{
"domains": [
{"domain": "docs.example.org", "repo": "example/docs", "required_paths": ["/", "/getting-started/"]},
{"domain": "www.example.net"}
],
"alert_webhook_url": "https://hooks.example.com/pages-watch"
}

The default input checks choosealicense.com with the paths / and /licenses/, and semver.org with the path /. Both are stable GitHub Pages sites with custom domains, so the default run gives two PASS verdicts.

Output

One record for each domain

FieldDescription
domain, repoThe domain and the repository from the input.
verdictPASS, WARN or FAIL.
previous_verdictThe stored verdict from the previous complete check, or null.
changedTrue when previous_verdict exists and is different from verdict.
reasonsThe reason codes. See the tables below.
check_incompleteTrue when the check was not complete. See Incomplete checks.
dnsFor the domain and its partner: the name, the role, the DNS status, and each A, AAAA and CNAME record with pages_target (true or false).
dns_points_at_pagesTrue when the domain has one or more GitHub Pages target records.
non_pages_recordsEach record that is not a GitHub Pages target, as name TYPE value.
https_checksFor each path: the URL, the HTTP status, the final URL, the number of redirects, ok and the error.
http_to_httpsTrue or false. Null when the HTTP request got no response.
http_redirect_locationThe first redirect target of the HTTP request.
cert_hostname_matchTrue when the certificate is valid for the domain name. False on a host name mismatch.
cert_validTrue when the certificate is trusted. False when it is expired, self-signed or not trusted for another reason.
tls_errorThe TLS error text, when there is one.
dangling_domain_riskTrue when DNS points at GitHub Pages and the answer is the GitHub Pages "site not found" 404.
pages_apiWhen a token and a repo are given: status, cname, public, https_enforced, certificate_state, certificate_expires_at, html_url, http_status and error. Otherwise null.
alert_status, alert_errorsent or failed, when an alert was sent for this domain.
checked_atThe time of the check.

FAIL reasons

ReasonMeaning
dns-not-foundThe domain has no A, AAAA or CNAME record (NXDOMAIN or an empty answer).
dns-lookup-failedThe resolvers gave SERVFAIL or another DNS error for the domain.
dns-not-pointing-at-pagesThe domain has records, but none is a GitHub Pages target.
dangling-domain-riskDNS points at GitHub Pages and GitHub Pages answers "site not found" for the domain.
certificate-hostname-mismatchThe HTTPS certificate is not valid for the domain name.
certificate-invalidThe HTTPS certificate is not trusted.
https-path-failedA required path did not answer HTTP 2xx over HTTPS.

WARN reasons

ReasonMeaning
dns-non-pages-recordThe domain points at GitHub Pages and also has a record that is not a GitHub Pages target.
partner-non-pages-recordThe www or apex partner has a record that is not a GitHub Pages target.
http-not-redirected-to-httpsHTTP does not redirect to HTTPS on the domain or its partner.
http-check-failedThe HTTP request for the redirect check got no response.
pages-api-errorThe GitHub Pages API did not return the Pages state.
pages-cname-mismatchThe custom domain in the Pages API is not the domain or its partner.
pages-https-not-enforcedThe Pages API reports that HTTPS is not enforced.
pages-certificate-not-approvedThe certificate state in the Pages API is not approved.
pages-build-erroredThe Pages API reports the build status errored.
dns-check-incompleteNo resolver answered, so the DNS checks were not done.
check-timed-outThe check of the domain took longer than 150 s.
check-errorThe check of the domain stopped on an unexpected error.

A domain with one or more FAIL reasons gets FAIL. A domain with only WARN reasons gets WARN. A domain with no reason gets PASS.

One summary record

FieldDescription
gate_passTrue when each domain had a complete check and no domain has FAIL.
domains_requested, domains_checkedThe domains in the input, and the domains with a complete check.
verdict_countsThe count of PASS, WARN and FAIL.
changed_count, changed_domainsThe domains whose verdict changed.
failing_domainsThe domains with FAIL.
incomplete_domainsThe domains with an incomplete check.
domains_not_checkedThe domains that were not started, because the maximum total charge was reached.
alerts_sent, alert_failuresThe webhook results.
state_errorThe error, when the state record was not read or not written.

The run ends SUCCEEDED for every result. A FAIL verdict, a failed gate and an unreachable domain are dataset results and a status message, not a failed run.

The verdict state

The Actor keeps the last verdict of each domain in the record VERDICTS of the named key-value store github-pages-domain-watch-state. A named store stays after the run ends, so the state continues from one scheduled run to the next.

  • The first check of a domain writes its verdict. It has no previous verdict, so changed is false and no alert is sent.
  • A run changes only the entries of its own domains. The entries of other domains stay.
  • When the Actor cannot read the state, it shows no change, sends no alert and does not write the state.
  • Two runs that end at the same time can write the state in the wrong order. Do not start two runs with the same domains at the same time.

Incomplete checks

A check is incomplete when no DNS resolver answered, when the check took longer than 150 s, or when it stopped on an unexpected error. An incomplete check does not change the stored verdict, sends no alert, is not charged as domain-checked, and sets gate_pass to false.

Webhook payload

The Actor sends one POST for each domain whose verdict changed:

{
"event": "verdict-changed",
"actor": "github-pages-custom-domain-go-live-and-dangling-domain-watch",
"domain": "docs.example.org",
"repo": "example/docs",
"verdict": "FAIL",
"previous_verdict": "PASS",
"reasons": ["dangling-domain-risk", "certificate-hostname-mismatch", "https-path-failed"],
"dns_points_at_pages": true,
"dangling_domain_risk": true,
"http_to_https": false,
"cert_hostname_match": false,
"https_checks": [{"path": "/", "status": null, "ok": false}],
"checked_at": "2026-09-15T06:00:04Z"
}

The payload never holds the token.

Pricing

This Actor uses pay-per-event pricing.

EventUnitPrice (USD)When it is charged
run-startedone actor run0.005Once for each run, after the input is valid and before the first request.
domain-checkedone custom domain checked for DNS, HTTPS, redirect, and Pages state in one run0.004For each domain with a complete check, for each verdict, also in the first run.
verdict-changedone domain whose verdict differs from the previous run0.01For each domain whose verdict changed. It is charged also when no webhook URL is given.

An incomplete check is not charged as domain-checked. The first check of a domain is not charged as verdict-changed. A domain that keeps the same verdict is charged domain-checked only.

The default maximum total charge for one run is USD 1.50. When a run reaches the maximum total charge, the Actor starts no more domains and lists them in domains_not_checked.

Examples

CaseRunsDomains per runVerdict changes per runCost per run (USD)Total (USD)
10 domains once each day for 30 days, no change301000.0451.35
One call after each of 20 deploys, 1 domain, no change20100.0090.18
One daily run of 10 domains with 2 verdict changes11020.0650.065
One run of 100 domains where every verdict changes11001001.4051.405

The run of 100 domains where every verdict changes costs USD 1.405, which is less than the default maximum total charge of USD 1.50.

Safety and limits

  • Each HTTP and HTTPS request target, and each redirect hop, is checked. A loopback, private or reserved address is refused.
  • At most 3 redirects for each request. The webhook POST and the Pages API call follow no redirect.
  • Each body read stops at 16 KB. Each request has a 10 s timeout and a 20 s deadline. The check of one domain has a 150 s deadline. At most 5 domains are checked at the same time.
  • Certificate verification is always on.
  • The token goes only to api.github.com. It is not logged and not written to the dataset or the webhook payload.

Scope

The Actor checks GitHub Pages hosting state. It does not compare certificates across endpoints after a renewal, it does not wait for DNS propagation after a cutover, and it does not audit robots.txt, sitemaps or llms.txt content.