NET::ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN is one of the few Chrome errors that almost nobody sees for the reason the internet says they see it. Most guides describe it as a site owner’s configuration mistake, something you caused by pinning the wrong key and can undo by reinstalling your certificate. That has not been true for years.
The error code itself is very much alive. Chrome still enforces it, still prints it, and still blocks the page with no way around it. What changed is who can trigger it. The feature that once let any website publish its own pins was removed from Chrome in 2018, and the only pins Chrome enforces today are the ones compiled into the browser itself. This guide explains what the error actually means now, the short list of things that genuinely cause it, and why several widely repeated fixes cannot affect it.
Quick answer:
NET::ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN means the certificate chain Chrome received did not contain any of the public keys Chrome has pinned for that hostname. Chrome’s pin list is built into the browser and covers only Google-owned domains plus three test domains, so an ordinary website cannot be pinned, and its owner can neither cause nor fix this error. The HTTP Public Key Pinning (HPKP) header that once let sites set their own pins was removed in Chrome 72 and is now ignored. If you hit this error on a Google domain, treat it as a signal that something is intercepting the connection with a publicly trusted certificate, and do not try to bypass it.
Table of Contents
- What the Error Actually Means
- Why a Website Owner Cannot Cause This Error
- What Actually Triggers It in 2026
- Why Antivirus and Corporate Proxies Usually Do Not Cause It
- How to Diagnose the Error
- How to Fix the Error
- What Does Not Fix This Error
- Protecting Your Own Site Without Pinning
- Frequently Asked Questions
What the Error Actually Means
Public key pinning is a rule that says: for this specific hostname, the certificate chain must contain at least one of these specific public keys. It exists because the normal certificate system trusts a large number of Certificate Authorities, and any one of them can technically issue a certificate for any domain. Pinning narrows that down. Even if an attacker persuades a trusted CA to issue a certificate for a pinned domain, the browser rejects it, because the key in that certificate is not on the approved list.
Chrome checks pins as the last step of certificate validation, after the chain has already been verified successfully. That ordering matters and explains a lot about this error. If the certificate were expired, self-signed, or issued for the wrong hostname, you would get a different error and the pin check would never run. Reaching the pin check means the certificate was otherwise valid and trusted. The connection was then rejected anyway, purely because the keys were wrong for that host.
In Chromium’s source, the error is defined as number -150 with a one-line description that gives the whole game away: the certificate did not match the built-in public key pins for the host name. Built-in is the operative word. The pins ship inside Chrome. They are not something a server sends.
Chrome also treats the failure as fatal. Having a pin entry for a hostname is by itself enough to make certificate errors on that host non-overridable, so the interstitial you get has no “Proceed anyway” link and no way to add an exception. This is the error that is supposed to catch a real attack in progress.
Why a Website Owner Cannot Cause This Error
There was a time when this error really was a site owner’s problem. Between 2015 and 2018, a website could send an HTTP response header called Public-Key-Pins that told browsers which keys to accept for that domain, and for how long. The mechanism was called HTTP Public Key Pinning, or HPKP. If you pinned a key you later stopped using, or forgot to pin a backup key, visitors were locked out of your site until the pin expired. There was no way to undo it remotely.
That failure mode is exactly why the feature was abandoned. Adoption stayed very low, the risk of locking yourself out was high, and attackers could use it offensively by pinning keys they controlled. Chrome deprecated HPKP in 2017 and removed it entirely in Chrome 72. Firefox dropped it in its own version 72. Chromium’s networking code now carries a plain statement in the source that it no longer implements HPKP, and the remaining function that adds dynamic pins is reachable only through Cronet, the networking library that Android apps embed.
Three consequences follow, and they overturn most of the advice published about this error:
- Sending a Public-Key-Pins header does nothing. Chrome ignores it. You cannot pin your site by accident, because you cannot pin it at all.
- You cannot opt your site into Chrome’s pin list. The list is a file maintained by hand inside Chromium’s source code, so a domain can only be added by a change to Chromium itself. The HSTS preload list takes public submissions through hstspreload.org; that site does not handle pinning, and no equivalent exists for it.
- Reinstalling your certificate changes nothing. If this error appears when someone visits your site, replacing your certificate cannot resolve it, because no pin for your domain exists in the first place.
So who is on the list? Chrome’s preloaded pin list is tiny and grows only slowly: fewer than 400 entries, three of them test domains and every other one a Google-owned property: google.com and its country variants, gmail.com, youtube.com, android.com, appspot.com, googleapis.com, doubleclick.net, blogspot.com and several chromium.org subdomains such as bugs.chromium.org. Every one of them maps to a single pinset containing Google Trust Services and GlobalSign keys. There are no third-party sites on it.
A few implementation details are worth knowing because they explain inconsistent reports:
- Static pin enforcement is compiled in only for official Google Chrome builds, and it is switched off on iOS. Other Chromium-based browsers may not enforce these pins at all, which is why a page that fails in Chrome can load in a Chromium build or on an iPhone.
- The list is delivered through Chrome’s component updater as well as being compiled in, so it can be refreshed without a full browser update.
- The list has a freshness deadline of 70 days. If Chrome’s copy has not been updated within that window, pin enforcement is skipped entirely rather than applied with stale data. Pinning fails open, not closed.
- Chrome 106 turned on pin enforcement for Android by default, bringing it to parity with the desktop versions, so mobile Chrome behaves like desktop Chrome here.
What Actually Triggers It
Once you know the pin list is Google-only and built in, the realistic causes reduce to a short list.
1. Something is intercepting a connection to a Google domain
This is the case the feature was built for. The connection is being terminated by something other than Google, and that something is presenting a certificate that chains to a publicly trusted root but does not contain a pinned Google key. Historically this is how real incidents were caught, including the misissued Google certificates that surfaced during the DigiNotar compromise. The Google domain does not have to be one you typed into the address bar. Pinned hostnames cover subdomains, and ordinary pages routinely load resources from googleapis.com, gstatic.com, google-analytics.com, googletagmanager.com and doubleclick.net, so the request that fails is often a font, script or ad rather than the page itself. If this happens on a network you do not control, such as public Wi-Fi or a hotel network, stop using that network for anything sensitive.
2. You loaded the deliberate test page
One of the three test entries in Chrome’s list is pinning-test.badssl.com, which is pinned to a hash that no real certificate can ever match. It exists so developers can reproduce the error on demand. Loading it in Chrome produces this exact message, and that is the correct, expected behaviour rather than a fault.
3. An Android app pinned its own keys
The one place dynamic pinning survives is Cronet, the Chromium networking library that Android apps can embed. An app developer can pin a set of key hashes for a hostname programmatically. When the server’s certificate is renewed with a new key and the app’s pin set was not updated to match, every user of that app is locked out until the app is updated. If you see this error inside an app rather than in the browser, this is almost certainly what happened, and only the app developer can fix it.
4. A managed device with a custom Chrome build or policy
On corporate hardware, the browser may be a managed or repackaged build with its own configuration. If pin enforcement is on but the machine’s interception setup was deployed in a way Chrome does not recognise as local, the two combine into this error. Your IT department is the right contact, and the diagnosis below will tell them precisely what to look at.
Why Antivirus and Corporate Proxies Usually Do Not Cause It
A lot of troubleshooting advice tells you to disable your antivirus when this error appears. On the face of it that sounds right: security suites with HTTPS scanning, and corporate proxies that inspect traffic, both work by decrypting your connection and re-signing it with their own certificate. That is textbook interception, so surely it breaks pinning.
Chrome deliberately allows it. When Chrome validates a certificate, it records whether the chain terminated at a root that ships with the browser or at a root that was installed locally on the machine. If the chain ends at a locally installed root, the pin check is skipped and the result is recorded as bypassed rather than violated. This behaviour is on by default. It is the reason antivirus HTTPS scanning and enterprise TLS inspection can work at all on pinned Google domains.
That exemption is what makes this error meaningful when it does appear. Work through what it rules out:
- If an interception root is installed and trusted on the machine, the pin check is bypassed and you see no error.
- If an interception root is not trusted at all, chain validation fails first and you get NET::ERR_CERT_AUTHORITY_INVALID instead.
- A pin error therefore means the chain validated against a publicly trusted root that is not on the pin list. That is a much narrower and more serious situation than a local proxy doing its job.
In short, “turn off your antivirus” is the wrong instinct. Turning it off will not usually change the outcome, and if it does, that tells you the product was intercepting with something other than a locally installed root, which is worth reporting to the vendor.
How to Diagnose the Error
The goal is to find out which certificate you are actually being served and who issued it. Three checks are enough.
1. Confirm the host is pinned at all
Chrome can tell you directly. Open its network internals page:
chrome://net-internals/#hsts
Enter the hostname under Query HSTS/PKP domain and read the result. The fields beginning with static_pkp, and in particular static_spki_hashes, show whether a preloaded pin set applies. If those come back empty, the host is not pinned in your copy of Chrome and the error is coming from somewhere else, such as an embedded app view.
2. Look at the certificate you are actually receiving
Run this from the same machine and the same network that shows the error, since the whole point is to catch a chain that differs from the real one:
openssl s_client -connect www.google.com:443 -servername www.google.com -verify_hostname www.google.com </dev/null
The -verify_hostname flag is not optional here. Without it, OpenSSL reports Verify return code: 0 (ok) even when the certificate was issued for a completely different hostname, because plain verification does not check the name against the host you asked for. With the flag, a mismatch is reported as Verify return code: 62 (hostname mismatch).
One caveat on macOS: the built-in /usr/bin/openssl is LibreSSL, which rejects this flag with “unknown option -verify_hostname”. Install OpenSSL through Homebrew and use that binary instead. Re-run openssl version afterwards to confirm you got it, since /usr/bin usually precedes Homebrew on PATH, and fall back to the full path /opt/homebrew/bin/openssl if it still reports LibreSSL.
To see every issuer in the chain at a glance, which is the fastest way to spot an unexpected middlebox:
openssl s_client -connect www.google.com:443 -servername www.google.com -showcerts </dev/null 2>/dev/null | grep -E "^ *[0-9]+ s:|^ *i:"
For a Google domain, the chain should be issued by Google Trust Services. Anything else, a security product’s name, a firewall vendor, your employer’s internal CA, tells you the connection is being intercepted and identifies what is doing it.
3. Compute the pin hash if you need to compare keys
Pins are base64-encoded SHA-256 hashes of the certificate’s Subject Public Key Info, not of the certificate itself. If you are an app developer checking a pin set against a renewed certificate, this produces the value to compare:
openssl x509 -in cert.pem -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
Because the hash covers the public key rather than the certificate, a renewal that reuses the same key keeps the same pin, while a renewal with a fresh key changes it. That single distinction is behind most app pinning outages.
How to Fix the Error
What you can do depends entirely on which cause the diagnosis pointed to.
- The chain shows an issuer you do not recognise, on a network you do not control. Disconnect and use a different connection, such as a mobile hotspot. If the error disappears on the other network, the first network was intercepting traffic. Do not enter credentials on the original network.
- The chain shows your employer’s CA or a security product on a managed device. Report it to IT with the issuer name from the second command. The usual cause is an inspection root that was not deployed into the certificate store Chrome reads, and the fix belongs with whoever manages the fleet.
- The error appears inside a mobile app. Update the app first, since a pin set corrected by the developer arrives in an update. If it persists, report it to the developer with the hostname and the date. There is no user-side setting for this.
- The error appears only in one Chrome profile. Test in a guest window. An enterprise policy or a managed profile applies configuration that a guest session does not, which narrows the problem to that profile’s management.
- You loaded pinning-test.badssl.com. Nothing to fix. The page is meant to fail.
One thing to avoid in every case: do not launch Chrome with certificate checking disabled, and do not install a root certificate that someone asks you to install in order to make the error go away. Those steps do remove the warning, and they remove exactly the protection that produced it. This is an error where succeeding at the workaround leaves you worse off than the error did.
What Does Not Fix This Error
A standard list of browser fixes circulates for almost every SSL error. For this one, none of it applies, and it is worth understanding why so you do not spend an afternoon on it.
- Clearing the cache and cookies. Pins are not cached content. The check runs against the live certificate chain on every connection, so an empty cache produces the same result.
- Disabling extensions or using Incognito. Extensions cannot alter certificate validation, which happens in the network stack before any extension sees the request. Incognito uses the same pin list.
- Correcting the system clock. A wrong clock causes NET::ERR_CERT_DATE_INVALID, a different error that stops validation earlier. Reaching a pin check means the dates already passed.
- Clearing the SSL state in Windows Internet Options. That button clears the client certificate cache used by Windows components. It has no connection to Chrome’s pin list.
- Flushing DNS or restarting the router. Neither changes which certificate is presented. If a network device is intercepting traffic, restarting it only restores the same interception.
- Reinstalling or reissuing your SSL certificate. This is the advice most often given to site owners, and it cannot work. Your domain is not in Chrome’s pin list, so there is no pin for a new certificate to satisfy.
- Removing a Public-Key-Pins header from your server. Worth removing as dead configuration, but it will not change browser behaviour, because Chrome stopped reading that header in version 72.
The net-internals delete button, specifically
The most common suggestion for this error, and the one previously given on this page, is to open chrome://net-internals/#hsts, find Delete domain security policies, enter the domain and click Delete.

That form deletes dynamic transport security state, the entries Chrome recorded from a site’s own HSTS headers. It cannot remove a preloaded entry, because preloaded pins are compiled into the browser rather than stored in your profile. Since HPKP was removed, dynamic pins do not exist in desktop Chrome at all, so on this error the button has nothing to delete.
The same page is still genuinely useful, just for the query function rather than the delete function. Use it as described in the diagnosis section to confirm whether a host is pinned. It is also the right tool for a real HSTS problem, where a stale dynamic entry forces HTTPS on a host that is no longer serving it.
Protecting Your Own Site Without Pinning
If you came here because you wanted the protection pinning offered, that goal is still reachable. The mechanisms that replaced it carry far less lockout risk, and none of them require your domain to be written into a browser’s source code.
- Certificate Transparency. Every publicly trusted certificate must be logged in public append-only logs, and Chrome refuses certificates that are not. Monitoring those logs tells you when a certificate is issued for your domain, whoever requested it. This is the direct replacement for pinning’s threat model, and unlike pinning it detects misissuance without any risk of locking out your visitors. See our guide to Certificate Transparency, and the related NET::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED error.
- CAA records. A DNS record that names which Certificate Authorities may issue for your domain. CAs are required to check it before issuing, so it prevents misissuance at the source instead of detecting it afterwards. It is a single DNS record and carries none of pinning’s lockout risk.
- HSTS. Forces browsers to use HTTPS for your domain and blocks downgrade attempts. Straightforward to deploy, and the preload list does accept public submissions.
Shorter certificate lifetimes also make pinning progressively less practical. As of March 2026, public certificates can be issued for no more than 200 days, dropping to 100 days in March 2027 and 47 days in March 2029. More renewals means more key changes, and each one is a chance for a pin to go stale. Most organisations now handle this with ACME certificate automation, which requests, installs and renews certificates without manual work.
Pinning does keep a legitimate niche in mobile apps, where the developer controls both ends and ships updates on a known schedule. Even there it needs backup pins and a release process that updates them ahead of certificate renewal. Our overview of certificate pinning covers the trade-offs. For a normal website, the answer in 2026 is that the browser has already taken this decision out of your hands.
Whatever you deploy, verify the result. Our free SSL Checker reports the chain your server actually sends, its expiry dates, and configuration problems that a padlock icon will not reveal.
Frequently Asked Questions
Yes. The error code is still defined in Chromium and Chrome still enforces it and prints it. What became obsolete is the cause most guides describe. The site-controlled pinning header behind those explanations was removed in 2018, so the error now comes from Chrome’s own built-in pin list rather than from anything a website configured.
No, and you almost certainly did not cause it. Chrome’s pin list contains only Google-owned domains and three test domains, and there is no way to add your site to it. Because your domain carries no pin, the check cannot fail against your own certificate. If a visitor reports this error while browsing your site, the failing request was most likely not to your server at all: pages commonly load Google-hosted fonts, analytics, tag manager or ad resources, and those hostnames are pinned. Ask which network the visitor was on and whether a security product is installed, since the cause sits on their connection rather than in your configuration.
No. Chrome removed support in version 72 and Firefox in version 72 of its own numbering. The header is ignored by current browsers. You can safely remove it from your server configuration, and you should, since leaving it in place suggests a protection that is not actually in effect.
Usually not. Chrome skips pin enforcement when a certificate chain ends at a root installed locally on the machine, which is how antivirus HTTPS scanning and enterprise inspection are able to work on pinned domains. That exemption is enabled by default. If you do get a pin error, it means the chain validated against a publicly trusted root instead, which is a narrower and more serious situation than routine local inspection.
Chrome treats certificate errors on pinned hosts as fatal and offers no override. Pinning exists to catch a certificate that is technically valid but wrong for that host, which is what an interception attack looks like. Letting users click through would defeat the purpose, so the interstitial has no bypass link and no exception can be added.
No. That form removes dynamic transport security entries stored in your profile, while the pins causing this error are compiled into the browser and cannot be deleted from it. The same page is still worth opening, though: its query function tells you whether a host is pinned at all, which is the first useful step in diagnosing the error.
Static pin enforcement is compiled into official Google Chrome builds and is disabled on iOS, so other Chromium-based browsers may not check these pins. A page loading elsewhere does not mean Chrome is wrong. It usually means the other browser is not performing the check, and the underlying certificate problem is still there.
Only with a plan for rotation. Pinning in an app is defensible because you control both the client and the server, but a certificate renewed with a new key invalidates the pin and locks out every user running the old version. Pin backup keys as well as current ones, and update the pin set in a release that ships before the certificate is renewed. With certificate lifetimes shortening to 47 days by 2029, that release cadence is the real cost.
Open pinning-test.badssl.com in Chrome. It is one of the three test entries in Chrome’s pin list, pinned to a hash no certificate can match, so it fails every time by design. It is a convenient way to confirm that pin enforcement is active in a given browser build before you investigate a real report.
For more SSL error troubleshooting, check our detailed tutorials about fixing different SSL errors, including NET::ERR_CERT_AUTHORITY_INVALID and Your Connection Is Not Private.
Save 10% on SSL Certificates when ordering from SSL Dragon today!
Fast issuance, strong encryption, 99.99% browser trust, dedicated support, and 25-day money-back guarantee. Coupon code: SAVE10

