Skip to content
Issue docs

Page served over HTTP instead of HTTPS

Criticalpage_not_served_over_httpsIssue 38

What is this issue?

This issue fires when the page URL uses the http:// scheme rather than https://.

It is the plainest of the five conditions that used to share a check titled Page not served over HTTPS, or certificate expired. The finding is about the scheme alone — it is raised even when the certificate probe fails, because the scheme is the fact that matters.

Why it matters

HTTP sends every request and response in clear text.

  • Browsers mark it as insecure. Chrome and others show a "Not secure" indicator in the address bar, and warn outright on any page with a form.
  • HTTPS is a ranking signal. Google has used it as one since 2014, and prefers the HTTPS URL when choosing a canonical between equivalent HTTP and HTTPS pages.
  • Anything in transit can be read or altered — credentials, session cookies, and the page content itself, which ISPs and public Wi-Fi have historically used for ad injection.
  • Modern browser features require a secure context. Service workers, geolocation, the clipboard API and HTTP/2 are unavailable over plain HTTP.

How to fix it

  1. Obtain a certificate. Let's Encrypt issues them free and most hosts automate renewal.

  2. Redirect HTTP to HTTPS with a 301, so the redirect is permanent and link equity transfers:

    server {
      listen 80;
      server_name example.com www.example.com;
      return 301 https://$host$request_uri;
    }
  3. Update internal references — canonical tags, sitemap URLs, hreflang, internal links, and any hard-coded asset URLs — to https://. Leaving these pointing at HTTP creates a redirect on every request.

  4. Fix mixed content. Sub-resources loaded over HTTP on an HTTPS page are blocked or downgrade the lock icon; these are reported separately.

  5. Add HSTS once HTTPS is confirmed working, so browsers never try HTTP again.

  6. Update Search Console to the HTTPS property and resubmit your sitemap.

Examples

1. A page served over plain HTTP

Problem — the page was fetched at:

http://acme.com/checkout

Everything on it, including anything typed into a form, travels unencrypted and can be read or rewritten in transit. Browsers mark the page "Not secure".

Fixed — serve it over TLS and redirect the old address permanently:

https://acme.com/checkout

HTTP/1.1 301 Moved Permanently
Location: https://acme.com/checkout

2. A site on HTTPS with one section left behind

Problem — the main site is HTTPS, but a legacy subsection was never migrated, so a handful of crawled URLs raise this issue:

https://acme.com/            ✓
https://acme.com/products    ✓
http://acme.com/legacy/faq   ✗
http://acme.com/legacy/docs  ✗

Fixed — bring the section onto the same certificate and redirect it. A site-wide HTTP → HTTPS redirect at the edge is what stops the next stray path recurring.

3. Certificate problems are reported separately

An HTTPS page whose certificate expired last week does not raise this issue. The scheme is https:, so the statement "page is served over HTTP" would simply be false.

https://acme.com/  →  certificate expired 2026-08-14

That is ssl_certificate_expired (#39). This check runs first, and when it fires the certificate checks do not — a page with no TLS has no certificate to assess.

How PixyScan detects this

  1. Scheme check. The crawler reads the protocol of the URL it fetched.

  2. Pass/fail.

    • Fails when the scheme is http:, with the message "Page is served over HTTP rather than HTTPS."
    • Passes when the scheme is https:. The certificate's own health is then assessed by the four separate certificate checks.
  3. Precedence. This check runs first, and when it fires the certificate checks do not — a page with no TLS has no certificate to assess.

  4. Scope. Page-level — evaluated for each crawled URL.

What we store

Storage Level

Page Level — evaluated for each crawled URL.


Database Table / Prisma Model

PageSecurityHeader

One row per crawled URL, keyed by urlId. This is the model the HTTPS and certificate checks (#38, #39) are mapped to.


Fields Used

Field Type Description
urlId String The crawled URL this row belongs to. The scheme this issue reads comes from Url.url
sslCertificateIssuer String? null on an HTTP page — no certificate is probed when there is no TLS
sslValidFrom DateTime? null on an HTTP page
sslValidUntil DateTime? null on an HTTP page

The scheme itself is not duplicated into a column: it is part of the address already stored on the Url row, and a second copy could only drift from it.

The three certificate columns are listed because this issue determines their value. When the page is plain HTTP the certificate probe does not run at all, so all three are written null — that is the row's record of "there was no TLS to inspect", not a failed read.


Detection Dependencies

  • HTTP Response — the protocol of the URL the crawler actually fetched

Further reading