<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ParallaxGrain</title>
    <description>The latest articles on DEV Community by ParallaxGrain (@parallaxgrain).</description>
    <link>https://dev.to/parallaxgrain</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4206991%2F24608930-86c3-4d15-b71e-b9e13fcfbdac.jpg</url>
      <title>DEV Community: ParallaxGrain</title>
      <link>https://dev.to/parallaxgrain</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/parallaxgrain"/>
    <language>en</language>
    <item>
      <title>Let's Encrypt for Internal Domains: What CT Logs Make Public</title>
      <dc:creator>ParallaxGrain</dc:creator>
      <pubDate>Sun, 15 Nov 2026 17:06:11 +0000</pubDate>
      <link>https://dev.to/parallaxgrain/lets-encrypt-for-internal-domains-what-ct-logs-make-public-4464</link>
      <guid>https://dev.to/parallaxgrain/lets-encrypt-for-internal-domains-what-ct-logs-make-public-4464</guid>
      <description>&lt;p&gt;Let's Encrypt for internal domains works: the DNS-01 challenge proves you control a domain without any server answering from the internet, and wildcard certificates come the same way. What it does not do is keep the name private. Every certificate a browser trusts is written to public Certificate Transparency (CT) logs. A service on a private address behind a VPN therefore still has a public hostname, and its issue dates and renewals are on record for anyone to read.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A public certificate means a public name. Choose a certificate per host, a wildcard or a private CA by how much of the name you can afford to publish, and protect every service as if its name is already known.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What a certificate publishes the moment it is issued
&lt;/h2&gt;

&lt;p&gt;Before issuing, a CA submits a precertificate to the logs. It is the certificate-to-be plus a critical extension, called the poison, that makes standard clients refuse it. The logs answer with signed timestamps (SCTs), and the CA embeds them in the real certificate. Nearly every CA works this way, so the hostname is public before the certificate exists. Chrome and Apple platforms both require signed proof from logs run by at least two separate organizations, so a publicly trusted CA cannot skip the step and a site owner cannot opt out.&lt;/p&gt;

&lt;p&gt;The log entry holds the whole certificate. For a domain-validated certificate, the kind Let's Encrypt issues, that means the names it covers, the issuer and the validity dates. Neither the server's address nor what it runs is in the entry. The leak is the name, which usually tells you what the host is for. Internet-wide scans already aggregated certificates, but the logs make the collection complete and early, and let anyone search it by name without connecting to your server. The entries for a domain, read as a list, give a stranger:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the services you run, from labels such as vault, grafana, jenkins or vpn;&lt;/li&gt;
&lt;li&gt;products and customer names before any announcement;&lt;/li&gt;
&lt;li&gt;the date each host appeared and whether its certificate keeps renewing;&lt;/li&gt;
&lt;li&gt;a ready target list, if the same names also resolve in public DNS.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Newer logs publish their contents as plain files that any client can download, and some add a compact list of just the names. For logs that Chrome accepts, the time a log may take to include an entry is capped at one minute for these static logs and four hours for the older kind. Soon after a Let's Encrypt certificate is logged, automated crawlers can find the new hostname and request it, and a public web server sees that traffic in its access log. Logs are append-only, so a name stays listed after its certificate expires or is revoked. The &lt;a href="https://packet.guru/blog/certificate-transparency-subdomains" rel="noopener noreferrer"&gt;full Certificate Transparency background&lt;/a&gt; covers logs, SCTs and browser enforcement in more detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's Encrypt for internal domains: what DNS-01 solves and what it publishes
&lt;/h2&gt;

&lt;p&gt;Let's Encrypt checks control of a name with a challenge. HTTP-01 needs a web server answering on port 80. DNS-01 needs only a TXT record in the domain's public DNS, so it works for hosts that are not exposed to the internet, and only DNS-01 can issue a wildcard. The renewing machine then holds a DNS API credential, and one that can edit your whole zone is a risk on a web server, so scope it narrowly or run the validation elsewhere.&lt;/p&gt;

&lt;p&gt;The name must sit under a domain you own in public DNS: public CAs may not issue for names that do not end in a registered top-level domain, so names ending in lan or local are out.&lt;/p&gt;

&lt;p&gt;On the publishing side, Let's Encrypt submits every certificate it issues to CT logs. Its default lifetime is 90 days, with renewal advised every 60, and six-day certificates are opt-in. Industry rules cap lifetimes at 200 days now, 100 from March 2027 and 47 from March 2029, so a per-host certificate puts the same name into the logs more often each year.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wildcard certificate subdomains: what stays hidden
&lt;/h2&gt;

&lt;p&gt;A wildcard certificate for *.lab.example.com covers exactly one label below lab.example.com. It matches vault.lab.example.com and rejects a.vault.lab.example.com or api.example.com. The log shows the wildcard and the zone label, lab, and none of the hosts under it, so the individual service names never appear.&lt;/p&gt;

&lt;p&gt;What a wildcard does not hide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Guessable names. A dictionary of common labels such as mail, dev, vpn and staging, each checked in DNS, finds hosts whatever certificate they use.&lt;/li&gt;
&lt;li&gt;Any host that also gets its own certificate, even once, from another CA or a test run.&lt;/li&gt;
&lt;li&gt;Names published in public DNS. Internal-only DNS answers, often called split-horizon, close that route.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Are wildcard certificates less secure?
&lt;/h2&gt;

&lt;p&gt;A wildcard is less secure in one respect: what a stolen key is worth. Its private key sits on every machine that serves a name under it, so the weakest host exposes all of them. Whoever holds the key can impersonate any name in the zone to anyone whose traffic they can redirect. Give each environment its own zone and its own wildcard, and keep the key off machines that do not serve it. The domain owner can also narrow who may issue at all: CAA records list the authorized CAs and can carry a separate rule for wildcard names.&lt;/p&gt;

&lt;h2&gt;
  
  
  Private certificate authority for internal names
&lt;/h2&gt;

&lt;p&gt;A certificate from your own CA never reaches the public logs. The logs do not accept certificates from CAs that browsers do not trust by default, and CT applies only to publicly trusted CAs, so a certificate signed under a root you installed yourself is outside it. For names only your organization uses, a private CA is the usual answer. The price is operational. You run the CA or rent a hosted one, guard its key, and install its root on every device that must trust it. That rules out visitors' phones and anything you do not manage.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;What public logs show&lt;/th&gt;
&lt;th&gt;Who trusts it&lt;/th&gt;
&lt;th&gt;What it costs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Public CA, one certificate per host&lt;/td&gt;
&lt;td&gt;Every hostname, at issuance and at each renewal&lt;/td&gt;
&lt;td&gt;Every browser and device&lt;/td&gt;
&lt;td&gt;Names, dates and renewal rhythm are public&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Public CA, wildcard&lt;/td&gt;
&lt;td&gt;The wildcard and the zone label&lt;/td&gt;
&lt;td&gt;Every browser and device&lt;/td&gt;
&lt;td&gt;One key on every host, one label deep, DNS credentials for issuance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Private CA&lt;/td&gt;
&lt;td&gt;Nothing, the logs refuse its certificates&lt;/td&gt;
&lt;td&gt;Only devices that installed your root&lt;/td&gt;
&lt;td&gt;You run the CA and distribute the root&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Certificate transparency monitoring: what to do about it
&lt;/h2&gt;

&lt;p&gt;Logs also work in your favor, because a certificate you did not request shows up in them as well. A monitor reads the logs for your domain and sends an alert for each new certificate. Cloudflare's CT Monitoring, generally available on every plan since August 2026, is opt-in and emails you about certificates for your domain from any other issuer. It only watches your own names, so a certificate for a lookalike domain raises no alert.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Look up your domain as an outsider would. The &lt;a href="https://packet.guru/web/subdomain-finder" rel="noopener noreferrer"&gt;Subdomain Finder&lt;/a&gt; from packet.guru combines Certificate Transparency data from crt.sh with roughly a thousand common names, checks each in DNS and lists the names that exist now, showing the address, country and network of each. A name that only survives in an old certificate and no longer resolves is dropped, so search crt.sh as well for the full history.&lt;/li&gt;
&lt;li&gt;Sort every name as reachable from outside or internal. An internal name with its own public certificate is a candidate for a wildcard on a separate zone, or for a private CA. The two combine: a public wildcard for services outside visitors must reach, a private CA for the rest.&lt;/li&gt;
&lt;li&gt;Treat every label as public. Keep customer names, unreleased products and role hints such as prod or admin out of hostnames that will ever get a public certificate.&lt;/li&gt;
&lt;li&gt;Put real access control on the service itself. Login, a VPN or an allowlist has to carry the protection, because the name will not.&lt;/li&gt;
&lt;li&gt;Check what each server presents: the certificate it serves lists its Subject Alternative Names, issuer and validity window, and any SSL checker shows them. Then turn on monitoring and publish CAA records.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>webdev</category>
      <category>security</category>
      <category>devops</category>
      <category>networking</category>
    </item>
    <item>
      <title>Tor vs VPN vs Proxy: Who Can See Your Traffic</title>
      <dc:creator>ParallaxGrain</dc:creator>
      <pubDate>Fri, 13 Nov 2026 14:00:00 +0000</pubDate>
      <link>https://dev.to/parallaxgrain/tor-vs-vpn-vs-proxy-who-can-see-your-traffic-3ehd</link>
      <guid>https://dev.to/parallaxgrain/tor-vs-vpn-vs-proxy-who-can-see-your-traffic-3ehd</guid>
      <description>&lt;p&gt;Tor vs VPN vs proxy usually gets argued on speed and price. A better first question is which watcher you want out of the picture and which one you are willing to let in. The café Wi-Fi, your ISP and the site you open each see part of your connection by default, and each of the three tools removes some of them by adding another.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A VPN or a proxy hands one operator both your address and where you go. Tor is built so that no single relay holds both.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What a VPN provider can see
&lt;/h2&gt;

&lt;p&gt;A VPN puts all of your device's traffic into one encrypted connection to the provider's server, which then opens the real connections for you. The Wi-Fi and the ISP now see one destination, the VPN server, plus how much you send and when. The provider sits where your ISP sat. It sees your real IP address, the address of every site you reach, the content of any plain HTTP page and, on HTTPS sites, the site name your browser announces at the start of the connection (the SNI field) unless the site uses Encrypted Client Hello, which encrypts it. Names looked up through the provider's DNS resolver, the server that turns site names into addresses, are readable too.&lt;/p&gt;

&lt;p&gt;The tunnel doesn't hide that it exists. WireGuard, for one, doesn't disguise itself and leaves obfuscation to layers above it, so a filter can pick VPN traffic out without reading it.&lt;/p&gt;

&lt;p&gt;What the provider stores is the open question, and a no-logs promise can't be checked from outside, because nobody can inspect what a server didn't write down. An independent audit narrows the doubt but describes one configuration at one moment. A VPN fits when the watcher you worry about is the network around you and you trust the company more than that network.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a proxy operator can see
&lt;/h2&gt;

&lt;p&gt;A proxy relays requests only for the apps configured to use it. The operator sees your IP address and the destination of everything those apps send, which is the VPN provider's position with less cover on the way there. How much cover depends on the type:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTTP proxy, plain HTTP site. The app hands over the whole URL, so the operator reads the request and the response.&lt;/li&gt;
&lt;li&gt;HTTP proxy, HTTPS site. The app sends a CONNECT request that names only a host and a port. After that the proxy forwards bytes in both directions without reading them, but it already knows the host.&lt;/li&gt;
&lt;li&gt;SOCKS5. In everyday use nothing is encrypted: the destination, an IP address or a hostname, crosses the network readable, and so does the password if the proxy requires a login.&lt;/li&gt;
&lt;li&gt;HTTPS proxy. The connection to the proxy is wrapped in TLS, the encryption behind HTTPS, so the Wi-Fi sees only the proxy. The operator's view doesn't change.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two details decide who else learns where you browse. A proxy may pass your address on to the site in a Forwarded header, the standard way for a proxy to tell a site who the original client was. And a SOCKS5 client that looks up the site name itself sends that lookup to your own resolver, outside the proxy. Handing the name to the proxy moves the lookup, and the knowledge, to the operator. A proxy therefore fits a narrow job: giving one app another address.&lt;/p&gt;

&lt;h2&gt;
  
  
  What each Tor relay sees
&lt;/h2&gt;

&lt;p&gt;Tor sends traffic through a circuit of three volunteer-run relays. Your client wraps the request in one layer of encryption per relay, and each relay can remove only the layer addressed to it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Guard, the entry. It sees your IP address and that you are connecting to Tor. It can't see the site.&lt;/li&gt;
&lt;li&gt;Middle. It sees the relay before it and the relay after it, and neither you nor the site.&lt;/li&gt;
&lt;li&gt;Exit. It sees the site you reach, resolves the name, and reads the content when the connection isn't HTTPS. It doesn't see who you are, and the site sees the exit's address instead of yours. Exits have been caught tampering with unencrypted connections.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your ISP sees a connection to a Tor relay. Relay addresses are public, so a network can recognize or block them, and a website can challenge or block exit traffic, which many do. A bridge, a relay missing from the public list, makes the first hop harder to block.&lt;/p&gt;

&lt;p&gt;The guard stays the same for months, on purpose. With a fresh entry and exit for every circuit, an attacker who watches a slice of the network would get a new chance to land on both ends each time. A fixed guard turns repeated chances into a single draw.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tor vs VPN: which one is more secure
&lt;/h2&gt;

&lt;p&gt;A VPN wins on speed and coverage: it carries a whole device's traffic rather than TCP streams alone, to a server you chose. Tor wins on how little any single party learns, and pays for it in speed, because traffic bounces through volunteers' servers around the world. Each also fails somewhere specific. A VPN fails at its operator: a compromised or careless company exposes your address next to your destinations in one spot. Tor fails when one party can watch both ends. An observer who sees you and also sees the site or the exit can line up the timing and volume of what goes in with what comes out, and Tor doesn't defend against that.&lt;/p&gt;

&lt;p&gt;All three fail at the login form. Log in to an account through a VPN, a proxy or Tor and the site knows who you are, whatever address it sees. Tor keeps your location apart from your destination, and what you type is still up to you.&lt;/p&gt;

&lt;p&gt;Stacking a VPN on Tor is an advanced setup rather than a free upgrade. Configured wrongly, it can weaken the protections Tor gives you, and the usual advice is to skip it unless you know how to configure both. The reason people reach for it, hiding Tor use from the network they are on, is what a bridge is for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which design fits which threat
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Threat&lt;/th&gt;
&lt;th&gt;Fits&lt;/th&gt;
&lt;th&gt;Who still sees what&lt;/th&gt;
&lt;th&gt;Where it fails&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Your ISP or the Wi-Fi owner&lt;/td&gt;
&lt;td&gt;VPN, or Tor&lt;/td&gt;
&lt;td&gt;VPN: the company sees your address and destinations. Tor: the guard knows your address, the exit knows the site&lt;/td&gt;
&lt;td&gt;Both show that you use them, unless Tor goes through a bridge&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The site seeing your IP&lt;/td&gt;
&lt;td&gt;VPN, Tor or a proxy&lt;/td&gt;
&lt;td&gt;The site sees a VPN, exit or proxy address&lt;/td&gt;
&lt;td&gt;An account you log in to; the reputation of a shared address&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Both at once&lt;/td&gt;
&lt;td&gt;Tor Browser, or a VPN if one company may see everything&lt;/td&gt;
&lt;td&gt;Tor: no relay holds both ends&lt;/td&gt;
&lt;td&gt;Timing match when both ends are watched&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A network that blocks Tor or VPNs&lt;/td&gt;
&lt;td&gt;Tor with a bridge&lt;/td&gt;
&lt;td&gt;The bridge sees your address, the network sees a connection to it&lt;/td&gt;
&lt;td&gt;Some countries detect certain bridges&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A single app that needs a different address&lt;/td&gt;
&lt;td&gt;Proxy&lt;/td&gt;
&lt;td&gt;The operator sees that app's traffic&lt;/td&gt;
&lt;td&gt;Plain HTTP and SOCKS5 proxies leave the first leg readable&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Shadowsocks, SSH tunnels, iCloud Private Relay, multi-hop VPNs and the two orders of Tor plus VPN are compared in the &lt;a href="https://packet.guru/blog/vpn-vs-proxy-vs-tor" rel="noopener noreferrer"&gt;full VPN vs proxy vs Tor guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  See whose address a site gets
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Start with your normal connection and run the &lt;a href="https://packet.guru/whoami" rel="noopener noreferrer"&gt;Privacy &amp;amp; Trust Index&lt;/a&gt; scan. The DNS Privacy card shows who answers your lookups. ISP DNS means your provider answers them and can read them.&lt;/li&gt;
&lt;li&gt;Turn on the VPN, set the proxy in your browser, or open Tor Browser, and scan again. The IP Reputation card names the kind of address the site now sees, with labels such as VPN / PROXY and TOR EXIT NODE when the address is on a known list. A shared address inherits the history of whoever used it before, which the &lt;a href="https://packet.guru/blog/ip-reputation-clean-vs-toxic" rel="noopener noreferrer"&gt;IP reputation guide&lt;/a&gt; covers.&lt;/li&gt;
&lt;li&gt;Read DNS Privacy again. NO DNS LEAK means the VPN or proxy handles your lookups, DNS LEAK means they still escape to a regular provider, and DNS VIA TOR means the exit node resolves the names. Each result tells you who reads the site names you look up.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>webdev</category>
      <category>security</category>
      <category>networking</category>
      <category>privacy</category>
    </item>
    <item>
      <title>Are Passkeys Phishing Resistant? What Each Login Method Stops</title>
      <dc:creator>ParallaxGrain</dc:creator>
      <pubDate>Tue, 10 Nov 2026 07:20:06 +0000</pubDate>
      <link>https://dev.to/parallaxgrain/are-passkeys-phishing-resistant-what-each-login-method-stops-275m</link>
      <guid>https://dev.to/parallaxgrain/are-passkeys-phishing-resistant-what-each-login-method-stops-275m</guid>
      <description>&lt;p&gt;Passkeys are phishing resistant: a fake login page cannot collect anything that works on the real site. That is one attack out of several, and every login method stops some and walks into others. A password falls to a fake page, an SMS code to a SIM swap, an authenticator code to a page that passes it on in time, and malware already on the device can get around all of them.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A password or a code is something a fooled person can hand over. A passkey holds a key that signs only for the site it was made for, so a fooled person has nothing to hand over.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What each login method stops
&lt;/h2&gt;

&lt;p&gt;The password column assumes one memorable or reused password. The manager column assumes a unique random password for every site.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attack&lt;/th&gt;
&lt;th&gt;Password&lt;/th&gt;
&lt;th&gt;Password + SMS code&lt;/th&gt;
&lt;th&gt;Password + app code&lt;/th&gt;
&lt;th&gt;Password manager&lt;/th&gt;
&lt;th&gt;Passkey&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Fake login page&lt;/td&gt;
&lt;td&gt;Fails&lt;/td&gt;
&lt;td&gt;Fails, the page relays the code&lt;/td&gt;
&lt;td&gt;Fails the same way&lt;/td&gt;
&lt;td&gt;Partly, autofill skips lookalike addresses&lt;/td&gt;
&lt;td&gt;Stops&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reused password (credential stuffing)&lt;/td&gt;
&lt;td&gt;Fails&lt;/td&gt;
&lt;td&gt;Stops the login, the password stays exposed&lt;/td&gt;
&lt;td&gt;Same as SMS&lt;/td&gt;
&lt;td&gt;Stops, one password per site&lt;/td&gt;
&lt;td&gt;Stops, nothing to reuse&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Leak of the site's database&lt;/td&gt;
&lt;td&gt;Weak passwords fall first&lt;/td&gt;
&lt;td&gt;Cracked password still needs the code&lt;/td&gt;
&lt;td&gt;Same, unless the code seed leaks too&lt;/td&gt;
&lt;td&gt;Contained to one site&lt;/td&gt;
&lt;td&gt;Stops, only public keys are stored&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SIM swap&lt;/td&gt;
&lt;td&gt;Not involved&lt;/td&gt;
&lt;td&gt;Fails&lt;/td&gt;
&lt;td&gt;Stops&lt;/td&gt;
&lt;td&gt;Not involved&lt;/td&gt;
&lt;td&gt;Not involved&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Malware on your device&lt;/td&gt;
&lt;td&gt;Fails&lt;/td&gt;
&lt;td&gt;Partly&lt;/td&gt;
&lt;td&gt;Partly&lt;/td&gt;
&lt;td&gt;Partly&lt;/td&gt;
&lt;td&gt;Partly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lost or replaced phone&lt;/td&gt;
&lt;td&gt;Not involved&lt;/td&gt;
&lt;td&gt;Number moves to the new SIM through the carrier&lt;/td&gt;
&lt;td&gt;Codes are gone unless backed up&lt;/td&gt;
&lt;td&gt;Vault syncs, the master password unlocks it&lt;/td&gt;
&lt;td&gt;Synced: restored on sign-in. Device-bound: gone&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A manager fills a login only on the address saved with it, so a lookalike domain gets nothing automatically, but a password pasted in by hand defeats that. On an infected device no method is safe: a keylogger (software that records keystrokes) reads a typed password, and a stolen session cookie, the token a site gives your browser after sign-in, works whatever login produced it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Password hashing, salt and credential stuffing
&lt;/h2&gt;

&lt;p&gt;A site should never store your password, only a hash of it: a one-way scramble that can be recomputed but not reversed. A salt, a random value stored beside each hash, makes two accounts with the same password produce different hashes, which defeats precomputed lookup tables. Good schemes are also deliberately slow. A leaked table still lets an attacker guess offline at their own pace, and the passwords people choose most often fall first.&lt;/p&gt;

&lt;p&gt;Composition rules do not change that. P@ssw0rd has a capital, a digit and a symbol, and it appears in leaked-password data more than six million times. Current standards no longer ask sites to demand mixed character types. They ask them to reject passwords already known from leaks and to accept long ones, with 15 characters as the floor when a password is the only factor.&lt;/p&gt;

&lt;p&gt;The same example in a Short:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/am5jxstnm4s" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Credential stuffing is how leaks get used. Attackers take email and password pairs from one breach and try them, automatically, on other sites. It works only where a password was reused.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why SMS codes and authenticator apps still get phished
&lt;/h2&gt;

&lt;p&gt;An SMS code travels over the phone network, and a SIM swap puts it in the wrong hands: the attacker persuades your carrier to move your number to a SIM they hold, and every text, codes included, goes to them. That makes SMS the weakest of the common second steps. Microsoft starts retiring SMS and voice codes in Entra ID, its work and school sign-in, in February 2027.&lt;/p&gt;

&lt;p&gt;An authenticator app avoids the carrier. It computes a short code on the phone from a secret shared with the site and the current time, in 30-second steps by default, so a SIM swap never touches the code. The weakness is that the code knows nothing about where you type it. A fake page asks for the password, then for the code, and forwards both to the real site before the code expires. Any code a person reads and types can be relayed like this, whether it arrived by text or came from an app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Are passkeys phishing resistant? What the browser checks
&lt;/h2&gt;

&lt;p&gt;Creating a passkey makes your device generate a key pair for that one site. The private key never goes to the site: it stays in the device's protected storage or in a credential manager. The site keeps the public key, which can verify a signature but cannot make one. At sign-in the site sends a fresh random challenge, so a recorded answer is useless the second time, which is how a &lt;a href="https://packet.guru/blog/replay-attacks-signed-requests" rel="noopener noreferrer"&gt;replay attack&lt;/a&gt; is defeated. You unlock the key with a fingerprint, face or PIN, and the device signs two things: the challenge and the web address of the page making the request. The browser fills in that address itself, not the page and not you.&lt;/p&gt;

&lt;p&gt;A page on another domain cannot even request the real site's passkey: the browser compares the domain being asked for with the page's own address and refuses a mismatch, and the real site would turn down a response that was signed for another address.&lt;/p&gt;

&lt;p&gt;The fingerprint or face stays on the device. The site receives a signed response and a flag saying the user was verified.&lt;/p&gt;

&lt;h2&gt;
  
  
  The catch: recovery, fallbacks and the device itself
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Adding a passkey does not remove the password or the SMS code from an account unless you do. A phishing page can claim that passkeys are unavailable and offer those instead, and the weaker method is then phished as before. A Microsoft account can drop its password altogether.&lt;/li&gt;
&lt;li&gt;Synced passkeys come back when you sign in to the Apple or Google account, or to a manager such as 1Password or Bitwarden, from a new device and pass its checks, so that account becomes the thing to protect. Apple's keychain recovery needs the Apple Account password, an SMS reply and a device passcode. A device-bound passkey, on a security key for example, is gone with the device, which is why a second one should be registered.&lt;/li&gt;
&lt;li&gt;A passkey protects the sign-in, not the computer. Attacks published in August 2026 let malware already running on a Windows PC take over accounts protected by Google-synced passkeys in Chrome and extract all of them.&lt;/li&gt;
&lt;li&gt;The lock screen is part of the trust: anyone who can unlock the device can use its passkeys, so create them only on devices that are yours. On a computer that is not yours, scan the QR code it displays and approve on your phone; the passkey stays there.&lt;/li&gt;
&lt;li&gt;Portability is still uneven. A synced passkey lives in one provider's vault, and moving it between managers needs a shared format. The Credential Exchange Format is a proposed standard and iOS 26 can export to apps that support it, but the transfer protocol is still a working draft.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sync, device-bound keys and each platform's recovery are covered in the &lt;a href="https://packet.guru/blog/what-is-a-passkey" rel="noopener noreferrer"&gt;full passkey guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do today
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Add a passkey first to the accounts that can reset all the others: your main email address and the Microsoft, Apple or Google account you use most. Game accounts follow, since PlayStation, Nintendo and Roblox let you sign in with one.&lt;/li&gt;
&lt;li&gt;Create each passkey on a device you own, then add a second one on another device or a hardware security key and test it before changing anything else.&lt;/li&gt;
&lt;li&gt;Remove the fallbacks the site lets you remove, the password and the SMS code, and keep the recovery codes offline.&lt;/li&gt;
&lt;li&gt;For sites without passkeys, give each account its own long random password from a manager or from the &lt;a href="https://packet.guru/utility/password-generator" rel="noopener noreferrer"&gt;password generator&lt;/a&gt; on packet.guru, which makes strong random passwords locally in your browser. Use an authenticator app for the second step instead of SMS.&lt;/li&gt;
&lt;li&gt;Look up your email addresses in Have I Been Pwned and replace the password of any site you still use that shows up in a breach.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>webdev</category>
      <category>security</category>
      <category>cybersecurity</category>
      <category>authentication</category>
    </item>
    <item>
      <title>TCP Fingerprinting: What One Packet Tells a Server About Your OS</title>
      <dc:creator>ParallaxGrain</dc:creator>
      <pubDate>Sat, 07 Nov 2026 12:32:05 +0000</pubDate>
      <link>https://dev.to/parallaxgrain/tcp-fingerprinting-what-one-packet-tells-a-server-about-your-os-4ofa</link>
      <guid>https://dev.to/parallaxgrain/tcp-fingerprinting-what-one-packet-tells-a-server-about-your-os-4ofa</guid>
      <description>&lt;p&gt;A web server learns something about your machine before it parses a single header. The SYN packet that opens every TCP connection carries a hop budget, a window size, a segment size and a list of options, and your operating system picked all of them. TCP fingerprinting reads those values and guesses the OS behind the connection. It needs no JavaScript and no cookies, and the visitor never sees it happen.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A browser can claim any operating system. The first packet shows what the kernel behind the connection does, and a mismatch check only needs the two to disagree.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How TCP fingerprinting reads a SYN packet
&lt;/h2&gt;

&lt;p&gt;The handshake starts with the client's SYN, short for synchronize. The standards define each field but leave most values to the implementer, so every network stack fills the SYN in with its own defaults. Four of them carry signal, strongest first:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The TCP options and their order. The standard fixes how an option is encoded but not where it sits in the list, so each kernel has its own layout. In default settings, Linux writes SACK permitted and the timestamp right after the MSS and puts window scale last, Windows puts window scale second and sends no timestamp, and Apple systems send a timestamp and finish with an end-of-list byte. On their own these usually separate the three families, though versions and settings shift them.&lt;/li&gt;
&lt;li&gt;Initial TTL, the hop budget in the IP header. It is coarse, as the next section shows.&lt;/li&gt;
&lt;li&gt;Window size, how much data the sender accepts before it expects an acknowledgment, and the window scale option that multiplies it. Both follow buffer memory, version and tuning, so one system can show several numbers and different systems can show the same one.&lt;/li&gt;
&lt;li&gt;MSS, the biggest payload the sender will take in one segment. It describes the link, not the OS: the MTU minus the IP and TCP headers, so systems on the same Ethernet link normally send 1460 over IPv4.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  TTL 64 vs 128: the clue everyone quotes
&lt;/h2&gt;

&lt;p&gt;TTL, time to live, starts at the OS default, and every router on the path subtracts one. The server receives the starting value minus the number of hops, then rounds up to the nearest common start: 64, 128 or 255. A reading of 54 means a start of 64 and ten routers on the way. A reading of 117 means a start of 128 and eleven.&lt;/p&gt;

&lt;p&gt;The rule of thumb says 64 is Linux and 128 is Windows. Android runs on the Linux kernel and starts at 64, and so do macOS and iOS. That makes TTL a one-question test: Windows or Unix-like. It cannot tell a Linux server from a Mac, and either side can change it with a single system setting. IPv6 calls the field the hop limit, and a router can announce which default hosts should use, so the network may override what the OS would pick.&lt;/p&gt;

&lt;h2&gt;
  
  
  Passive OS fingerprinting vs Nmap OS detection
&lt;/h2&gt;

&lt;p&gt;Nmap's OS detection is the active kind. It sends up to 16 TCP, UDP and ICMP probes to open and closed ports on the target, built to exploit gaps in the standard, and matches the replies against a database of thousands of fingerprints. Passive tools such as p0f send nothing. They read packets that cross the wire anyway, often just one SYN. A website has little choice but the second kind for its visitors. Nmap itself works best when it finds at least one open and one closed TCP port, and a probe aimed at a visitor's public address lands on the home router, not on the laptop behind it.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Passive (p0f, JA4T)&lt;/th&gt;
&lt;th&gt;Active (Nmap OS detection)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Packets the observer sends&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Up to 16 probes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What it studies&lt;/td&gt;
&lt;td&gt;The client's SYN; p0f also reads the server's SYN+ACK&lt;/td&gt;
&lt;td&gt;Replies to crafted probes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What it needs from the target&lt;/td&gt;
&lt;td&gt;A connection that arrives anyway&lt;/td&gt;
&lt;td&gt;A reachable address and, for best results, a mix of open and closed ports&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Does the target notice&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Probes can set off alarms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typical user&lt;/td&gt;
&lt;td&gt;A website classifying its own visitors&lt;/td&gt;
&lt;td&gt;An admin auditing a network they own&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typical answer&lt;/td&gt;
&lt;td&gt;OS family and rough generation&lt;/td&gt;
&lt;td&gt;A ranked OS and version guess&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The active tools are visible to the passive ones: p0f ships signatures for Nmap's SYN scan and for its OS detection probes. JA4T takes the passive route and writes four values into one string a server can log per connection: window size, option order, MSS and window scale. It leaves out the TTL, which shifts with distance. The signature formats and licensing are covered in the &lt;a href="https://packet.guru/blog/passive-os-fingerprinting" rel="noopener noreferrer"&gt;passive OS fingerprinting guide&lt;/a&gt;. Application code rarely sees a SYN, so the reading usually happens at the edge: a firewall, load balancer or sensor.&lt;/p&gt;

&lt;h2&gt;
  
  
  TCP fingerprint anomaly: when the packet and the browser disagree
&lt;/h2&gt;

&lt;p&gt;The server fingerprints whoever opened the connection to it. A tunnel VPN carries your packets as they are, so your SYN arrives intact. A proxy opens a second connection, so the website is looking at the proxy's kernel, often Linux on a rented server. A CDN or load balancer that ends TCP shows the origin its own SYN and keeps yours for itself, and Tor does the same at its exit relays. &lt;a href="https://packet.guru/blog/vpn-vs-proxy-vs-tor" rel="noopener noreferrer"&gt;VPN vs proxy vs Tor&lt;/a&gt; lays out which tools forward packets and which open a connection of their own.&lt;/p&gt;

&lt;p&gt;Set that against the browser's claim, which an extension can rewrite in seconds, and you have a TCP fingerprint anomaly. Take a Windows laptop behind a Linux proxy: the User-Agent says Windows, the SYN says Linux, and the address often sits in a hosting network. Each signal is weak alone. Anti-fraud systems tend to weigh such signals together, so the visitor can end up with a CAPTCHA or a second sign-in prompt instead of a block. Automation hits the same check: a scraper in a Linux container can send any User-Agent, but its kernel sends a Linux SYN.&lt;/p&gt;

&lt;p&gt;The two directions carry different weight:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Linux SYN under a Windows or Apple claim is common and often innocent: a proxy, a relay service or a corporate gateway.&lt;/li&gt;
&lt;li&gt;A Windows or Apple SYN under a different claim is rarer, because few proxy servers run on those systems. It usually points to an edited claim, from a browser extension or an anti-detect profile.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;p0f has a flag for this check: it reports 1 when the User-Agent differs from the OS in a way proxying can explain, and 2 for an outright mismatch.&lt;/p&gt;

&lt;p&gt;A mismatch does not say which layer is wrong, or why. Matching proves little in the other direction, because some proxy providers offer a setting that makes the proxy's SYN look like another system. The SYN gives a family, not a version or a device, and p0f's own label for recent Macs adds "sometimes iPhone or iPad". It also needs TCP to be there at all. HTTP/3 runs on QUIC over UDP and has no SYN, though browsers first hear about HTTP/3 through a response header or a DNS record, so many connections still start on TCP.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check your own TCP fingerprint
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to the &lt;a href="https://packet.guru/whoami" rel="noopener noreferrer"&gt;Privacy &amp;amp; Trust Index&lt;/a&gt; and wait for the scan to complete. The TCP/OS Fingerprint card compares the system your connection points to with the one your browser reports.&lt;/li&gt;
&lt;li&gt;Read the status. OS MATCH means the two agree. OS MISMATCH means the connection reveals a different system than the browser reports, and the details can name what carried it, such as a VPN or a datacenter network. OS HIDDEN BY TOR means an exit relay opened the connection. PROBE UNREACHABLE means the fingerprint could not be read this time.&lt;/li&gt;
&lt;li&gt;Open the Connection Fingerprint panel lower on the page. Its TCP / IP rows show the Detected OS and Initial TTL, the raw Window, MSS and Window Scale values, the Options and your JA4T. Compare the TTL with 64 and 128, and the options with the layouts above.&lt;/li&gt;
&lt;li&gt;Turn a VPN or proxy on and scan again, then compare the Detected OS and the status with the first run.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>webdev</category>
      <category>security</category>
      <category>networking</category>
      <category>fingerprint</category>
    </item>
    <item>
      <title>JA4 Fingerprint: What It Reads and Why JA3 Stopped Working</title>
      <dc:creator>ParallaxGrain</dc:creator>
      <pubDate>Thu, 05 Nov 2026 14:00:00 +0000</pubDate>
      <link>https://dev.to/parallaxgrain/ja4-fingerprint-what-it-reads-and-why-ja3-stopped-working-57n</link>
      <guid>https://dev.to/parallaxgrain/ja4-fingerprint-what-it-reads-and-why-ja3-stopped-working-57n</guid>
      <description>&lt;p&gt;Two separate connections from the same Chrome open with a ClientHello, the opening message of each HTTPS handshake, and the extensions inside it come in a different order each time. Hash that list in the order it arrives, as JA3 does, and one browser produces a new fingerprint on nearly every connection. A JA4 fingerprint sorts the list first, so both connections give the same string, one that a rule or a database can match. Cloudflare, AWS WAF and Auth0 all read JA4 now.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A TLS fingerprint names the software that opened a connection. It says nothing about who is using that software or why.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why the JA3 fingerprint stopped working
&lt;/h2&gt;

&lt;p&gt;JA3 came out of Salesforce in 2017. It takes five fields from the ClientHello (TLS version, cipher suites, extensions, elliptic curves and curve point formats), lists the values in ClientHello order and hashes the string with MD5. The same application sends the same hello and gets the same 32-character hash, so defenders could trade hashes of known malware between organizations. The JA3 repository is archived now, and its author maintains JA4 instead.&lt;/p&gt;

&lt;p&gt;JA3 broke on ordering, which TLS leaves free: extensions may appear in any sequence, except that pre_shared_key must come last. Servers that key on Chrome's exact layout would make it hard for Chrome to change TLS later, so since Chrome 110 (2023) it shuffles its extensions on every new connection. The shuffle happens inside BoringSSL, Chromium's TLS library, which draws a fresh permutation for each handshake, so browsers built on Chromium's network stack inherit it. A JA3 rule written for one Chrome handshake now matches only the connections that happen to repeat that order.&lt;/p&gt;

&lt;p&gt;GREASE, the reserved placeholder values Chrome mixes into its lists to keep servers tolerant of unknown options, did not cause the breakage: JA3 skips them. Randomizing the cipher list, called cipher stunting, is another known way to dodge JA3.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a JA4 fingerprint reads
&lt;/h2&gt;

&lt;p&gt;JA4, published by FoxIO in 2023, reads the same ClientHello and prints three parts joined by underscores. Taken apart, a Chrome fingerprint like t13d1516h2_8daaf6152771_02713d6af862 says:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The first part is plain text. It opens with t for TLS over TCP (q is QUIC, d is DTLS), then 13 for the highest TLS version the client offers, here 1.3, then d if a server name was sent (i if not). Next come the counts of cipher suites (15) and extensions (16), and h2, the first and last character of the client's first ALPN protocol. That is the one it prefers: HTTP/2.&lt;/li&gt;
&lt;li&gt;The second part is the cipher suites sorted in hex order, hashed with SHA-256 and cut to 12 characters.&lt;/li&gt;
&lt;li&gt;The third part is the extensions sorted the same way (server name and ALPN left out, because part one covers them), followed by the signature algorithms in the order sent, hashed and cut the same way.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;GREASE values are ignored everywhere. Sorting is what cancels the shuffle: every ordering of the same extensions sorts to the same list. The signature algorithms stay in sent order, so a client that shuffled those would still change part three. For cipher suites the order is a real preference ranking, so sorting trades a little detail for stability.&lt;/p&gt;

&lt;p&gt;The readable first part is useful without any database lookup. Browsers advertise h2 there, while many scripting clients offer no ALPN at all and show 00 instead.&lt;/p&gt;

&lt;p&gt;JA4 is one member of the JA4+ family: JA4S fingerprints the server's reply, JA4H the HTTP request, JA4T the TCP handshake, JA4L latency, JA4X certificates. The licenses differ. The TLS fingerprint itself is open source under BSD 3-Clause, as JA3 is, while the other family members use the FoxIO License, which allows internal and academic use and not selling it inside a product without a separate license.&lt;/p&gt;

&lt;h2&gt;
  
  
  JA3 vs JA4 side by side
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;JA3&lt;/th&gt;
&lt;th&gt;JA4&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Introduced&lt;/td&gt;
&lt;td&gt;2017, Salesforce&lt;/td&gt;
&lt;td&gt;2023, FoxIO&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fields read&lt;/td&gt;
&lt;td&gt;TLS version, ciphers, extensions, elliptic curves, point formats&lt;/td&gt;
&lt;td&gt;Transport, TLS version, server name present or not, ALPN, ciphers, extensions, signature algorithms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Order&lt;/td&gt;
&lt;td&gt;As sent&lt;/td&gt;
&lt;td&gt;Ciphers and extensions sorted, signature algorithms as sent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GREASE&lt;/td&gt;
&lt;td&gt;Skipped&lt;/td&gt;
&lt;td&gt;Skipped&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Transport&lt;/td&gt;
&lt;td&gt;Not recorded&lt;/td&gt;
&lt;td&gt;First character: t, q or d&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output&lt;/td&gt;
&lt;td&gt;One 32-character MD5 hash&lt;/td&gt;
&lt;td&gt;Three readable parts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Same Chrome, two TCP connections&lt;/td&gt;
&lt;td&gt;Two different hashes&lt;/td&gt;
&lt;td&gt;The same fingerprint&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The full background on both formats and on the JA4+ family is in the &lt;a href="https://packet.guru/blog/TLS-Fingerprinting-JA3-JA4" rel="noopener noreferrer"&gt;TLS fingerprinting guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How bot detection uses a TLS fingerprint
&lt;/h2&gt;

&lt;p&gt;The handshake comes before the first HTTP request, and its shape comes from the TLS code inside the client, not from anything a script writes into a header. A script's HTTP library brings its own TLS defaults, while Chrome uses BoringSSL. A server therefore holds a claim (the User-Agent says Chrome) and a measurement (the handshake says otherwise), and three checks turn that into a signal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claim against handshake. A Chrome User-Agent on a handshake that looks like a script library is a mismatch. A JA4 nobody has seen before proves nothing by itself, because it can be just a new browser release.&lt;/li&gt;
&lt;li&gt;One layer against the next. HTTP/2 has its own fingerprint: which SETTINGS values the client sends and in what order, the WINDOW_UPDATE increment, any PRIORITY frames and the sequence of the request pseudo-headers. TCP has JA4T. Different parts of the client produce each layer, so a script that copies Chrome's ClientHello but keeps its library's HTTP/2 defaults disagrees with itself.&lt;/li&gt;
&lt;li&gt;The fingerprint's own record. Cloudflare's Bot Management can report, for each JA4, what happened over the last hour of its traffic: the share of requests with browser user agents, how many distinct IPs use it, how much it requests. A fingerprint seen almost only on non-browser traffic reads differently from one that a great many browsers share.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Matching all of this is possible. Libraries such as curl_cffi impersonate a real browser's ClientHello and HTTP/2 settings. Another route is to drive an actual browser, whose handshake is genuine by construction. Then the TLS layer has nothing to flag and the decision falls to other signals, which &lt;a href="https://packet.guru/blog/fake-browser-detection" rel="noopener noreferrer"&gt;fake browser detection&lt;/a&gt; covers for headless and anti-detect browsers.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a TLS fingerprint can't prove
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A proxy that terminates TLS replaces the fingerprint. Antivirus that inspects HTTPS and corporate gateways decrypt the traffic and start a second connection of their own, so the server sees the gateway's handshake, which can disagree with an honest browser's User-Agent.&lt;/li&gt;
&lt;li&gt;Encrypted Client Hello (ECH) hides the real hello from the path. It wraps the true ClientHello inside an outer one. A network observer can fingerprint only the outer hello, while the server that decrypts it still reads the inner one.&lt;/li&gt;
&lt;li&gt;Over HTTP/3 a browser has a second JA4, one starting with q instead of t, because TLS runs inside QUIC. The first QUIC packet is protected with keys derived from a connection ID sent in the clear, so any observer along the route can read the ClientHello in it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  See your own TLS fingerprint
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Start the &lt;a href="https://packet.guru/whoami" rel="noopener noreferrer"&gt;Privacy &amp;amp; Trust Index&lt;/a&gt; scan and wait until every card has a result.&lt;/li&gt;
&lt;li&gt;Find the TLS / JA4 Fingerprint card. It reads your TLS and HTTP/2 handshake and compares both with the browser your User-Agent reports. The answer is CONSISTENT, ENGINE MISMATCH, SPOOFED, AUTOMATION TOOL or UNVERIFIED. ENGINE MISMATCH can also come from a corporate proxy or a brand-new browser build, and UNVERIFIED means your fingerprint is not in the reference set yet, so nothing is concluded.&lt;/li&gt;
&lt;li&gt;Scroll to the Connection Fingerprint panel for the raw values: JA4, the older JA3, ECH status, the TCP row with JA4T and the HTTP/2 fingerprint.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>webdev</category>
      <category>security</category>
      <category>networking</category>
      <category>cybersecurity</category>
    </item>
    <item>
      <title>SNI Encryption: What Encrypted Client Hello Hides and What It Doesn't</title>
      <dc:creator>ParallaxGrain</dc:creator>
      <pubDate>Tue, 03 Nov 2026 14:00:00 +0000</pubDate>
      <link>https://dev.to/parallaxgrain/sni-encryption-what-encrypted-client-hello-hides-and-what-it-doesnt-78m</link>
      <guid>https://dev.to/parallaxgrain/sni-encryption-what-encrypted-client-hello-hides-and-what-it-doesnt-78m</guid>
      <description>&lt;p&gt;HTTPS over TLS 1.3 encrypts the certificate, the URL path and the page. The site's name still goes out in plain text, in a field called Server Name Indication (SNI) inside the very first message, the ClientHello. Your ISP can read it, and so can a café's Wi-Fi or a corporate firewall. SNI encryption closes that gap, and Encrypted Client Hello (ECH) is the standard that does it: RFC 9849, published in March 2026.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ECH hides which site you asked for. It does not hide where the connection goes, or the DNS lookup that came before it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How SNI encryption works in ECH
&lt;/h2&gt;

&lt;p&gt;The browser builds two hellos. The inner one carries the real name and the real ALPN list (the protocols it offers, such as HTTP/2 and HTTP/3) and is encrypted with a public key the site published in DNS. The outer one travels in plain text with a stand-in name.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The browser asks DNS for the site's HTTPS record, a record type that describes how to connect. If the record has an ech parameter, it holds the public key and the stand-in name, called the public_name.&lt;/li&gt;
&lt;li&gt;The browser encrypts the inner ClientHello to that key.&lt;/li&gt;
&lt;li&gt;It sends the outer ClientHello with the public_name in the SNI field and the encrypted inner one attached as an extension.&lt;/li&gt;
&lt;li&gt;The server decrypts the inner hello and finishes the handshake as the real site. If the key is stale or the server doesn't speak ECH, it answers as the public_name and, when it can, hands back fresh keys so the browser retries.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Sites behind the same provider that share a key and look alike on the wire form an anonymity set. An observer sees a connection to the provider and can't tell which of its sites it was.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who sees what
&lt;/h2&gt;

&lt;p&gt;What an ISP, a Wi-Fi owner or a firewall on the path can read:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What a network observer reads&lt;/th&gt;
&lt;th&gt;No ECH, plain DNS&lt;/th&gt;
&lt;th&gt;ECH, plain DNS&lt;/th&gt;
&lt;th&gt;ECH, encrypted DNS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Site name in the SNI field&lt;/td&gt;
&lt;td&gt;Readable&lt;/td&gt;
&lt;td&gt;Hidden&lt;/td&gt;
&lt;td&gt;Hidden&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Real ALPN list&lt;/td&gt;
&lt;td&gt;Readable&lt;/td&gt;
&lt;td&gt;Hidden&lt;/td&gt;
&lt;td&gt;Hidden&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Site name in the DNS lookup&lt;/td&gt;
&lt;td&gt;Readable&lt;/td&gt;
&lt;td&gt;Readable&lt;/td&gt;
&lt;td&gt;Hidden&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Destination IP address&lt;/td&gt;
&lt;td&gt;Readable&lt;/td&gt;
&lt;td&gt;Readable&lt;/td&gt;
&lt;td&gt;Readable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Provider's public_name&lt;/td&gt;
&lt;td&gt;Not used&lt;/td&gt;
&lt;td&gt;Readable&lt;/td&gt;
&lt;td&gt;Readable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Packet sizes and timing&lt;/td&gt;
&lt;td&gt;Readable&lt;/td&gt;
&lt;td&gt;Readable&lt;/td&gt;
&lt;td&gt;Readable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;URL path, cookies, page content&lt;/td&gt;
&lt;td&gt;Hidden&lt;/td&gt;
&lt;td&gt;Hidden&lt;/td&gt;
&lt;td&gt;Hidden&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The DNS resolver sees every name it resolves in all three setups, and the destination can read the real name, so both always know.&lt;/p&gt;

&lt;h2&gt;
  
  
  What stays visible with ECH
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The IP address. A connection has to reach a server, so the address is on the wire. When thousands of sites share a provider's addresses it says little. A site alone on its own address is identified by that address, and ECH adds nothing there.&lt;/li&gt;
&lt;li&gt;The public_name. Every ECH site at a provider shows the same stand-in, such as cloudflare-ech.com on Cloudflare. It tells an observer which provider the connection goes to, and a fixed name is easy to match. In November 2024 Russia began blocking connections that carry an ECH extension together with that visible name. Browsers also send a decoy ECH extension to sites without ECH, so the extension alone gives nothing away; the name does.&lt;/li&gt;
&lt;li&gt;Volume and timing. ECH pads the inner hello (the configuration carries a maximum_name_length for that) so its size doesn't hint at the name. The size and rhythm of the traffic after the handshake are another matter and remain visible.&lt;/li&gt;
&lt;li&gt;The rest of the outer hello. Cipher suites, extensions and their order are in plain text, and a TLS fingerprint such as JA4 is built from fields like these. They describe the client software, not the site.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Encrypted Client Hello and DNS
&lt;/h2&gt;

&lt;p&gt;The key for ECH lives in DNS, so DNS both delivers the key and leaks the name. With plain DNS, the lookup for the site and for its HTTPS record cross the network readable, which gives the name away before the handshake starts. A network that controls the answers can also delete the ech parameter. The browser then has no key and connects the old way, with the name in plain text. Once it holds a key, it doesn't quietly retry with a plain hello when the handshake fails, so a network that wants the name must remove the key beforehand or block the connection. Encrypted DNS (DoH, DoT or DoQ) closes the first two holes on the path, though the resolver you picked still sees every name.&lt;/p&gt;

&lt;h2&gt;
  
  
  ECH vs VPN
&lt;/h2&gt;

&lt;p&gt;A VPN and ECH hide different things from different observers. A VPN tunnels all traffic, so the local network sees only the VPN server, and the VPN provider takes the observer's seat, seeing destination addresses plus any names in handshakes and DNS queries that aren't encrypted. ECH removes the name from the handshake, so that observer can't read it there, though the addresses remain. Together they split the job: the VPN hides the destination addresses from your ISP, and ECH hides the handshake name from the VPN provider.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where ECH is switched on in 2026
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Chrome has had ECH on by default since version 117 (September 2023), Firefox since October 2023.&lt;/li&gt;
&lt;li&gt;Android 17 adds ECH at the platform level and pairs it with Private DNS, the system-wide encrypted DNS setting. Apps need a networking library that uses it: OkHttp 5.5.0 and later can enable it, the system HttpEngine follows in Android 17 QPR2 and WebView in a later release.&lt;/li&gt;
&lt;li&gt;OpenSSL 4.0, released in April 2026, is the first OpenSSL release with ECH, so software that builds on it can start supporting ECH.&lt;/li&gt;
&lt;li&gt;Cloudflare enables ECH by default on Free zones; other plans turn it on in the dashboard. Most domains that support ECH sit behind Cloudflare, so most of the anonymity set is one company's network.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What filters and firewalls do about ECH
&lt;/h2&gt;

&lt;p&gt;A filter that matches on the SNI loses its input once the name is encrypted. Filtering by name still works at the DNS resolver, which sees every name. Where that doesn't fit, a network can answer HTTPS queries without an ech parameter, or not at all, so clients never get a key. Managed browsers can switch ECH off: Chrome has an enterprise policy for it, and Firefox stops using ECH when the resolver returns no answer for a canary domain. The last resort is decrypting the traffic at a TLS-intercepting proxy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check a site and your own connection
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;a href="https://packet.guru/web/ech-check" rel="noopener noreferrer"&gt;ECH Checker&lt;/a&gt; looks up a domain's HTTPS record, reads the ech parameter and decodes the configuration, including the public_name that observers see. A domain with no ech parameter gives a browser no key to encrypt with, whatever the browser supports.&lt;/li&gt;
&lt;li&gt;The ECH Status card on the &lt;a href="https://packet.guru/whoami" rel="noopener noreferrer"&gt;Privacy &amp;amp; Trust Index&lt;/a&gt; reports whether the name of the site you visited was encrypted in your connection. When the name was hidden but your DNS still reveals it, the card says DNS STILL OPEN.&lt;/li&gt;
&lt;li&gt;Browser switches and server settings are in the &lt;a href="https://packet.guru/blog/ECH-Encrypted-Client-Hello-2026" rel="noopener noreferrer"&gt;ECH setup guide&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>webdev</category>
      <category>security</category>
      <category>privacy</category>
      <category>ech</category>
    </item>
    <item>
      <title>Browser Fingerprinting Protection: Randomize, Blend In or Block</title>
      <dc:creator>ParallaxGrain</dc:creator>
      <pubDate>Sat, 31 Oct 2026 05:58:53 +0000</pubDate>
      <link>https://dev.to/parallaxgrain/browser-fingerprinting-protection-randomize-blend-in-or-block-232n</link>
      <guid>https://dev.to/parallaxgrain/browser-fingerprinting-protection-randomize-blend-in-or-block-232n</guid>
      <description>&lt;p&gt;A page can ask the browser which graphics card it runs on, through WebGL, the browser's 3D graphics interface. An unprotected browser answers with the exact model. Brave answers with one word, "Brave", for the vendor and the renderer alike. That is deliberate: Brave decided the model is too identifying to give out, which makes it the simplest case of browser fingerprinting protection.&lt;/p&gt;

&lt;p&gt;A fingerprint works for a tracker only when it is distinctive (few other browsers match it) and stable (it survives from one session to the next). Defenses go after one or the other, and most browsers mix them.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A browser can make your fingerprint shared, shifting or unreadable. It can't make it disappear, because a page can't render without reading some of those values.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Three kinds of browser fingerprinting protection
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Blend in. Many browsers report identical values, so the fingerprint stops being distinctive: it points to a crowd instead of a person. Tor Browser and Mullvad Browser are built on this.&lt;/li&gt;
&lt;li&gt;Keep changing. The browser adds small random noise to what it returns, so the fingerprint is not stable: the same machine looks different to every site and again after a restart. Brave is built around this.&lt;/li&gt;
&lt;li&gt;Block. The browser stops scripts that appear on lists of known fingerprinters, or refuses to return the data at all, so there is nothing to read. Firefox, Safari, Edge and DuckDuckGo lean on lists like this, and Tor Browser also withholds canvas image data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Which move fits depends on the value. Canvas pixels and audio samples survive a nudge nobody can see. A name does not: a GPU model can only be replaced by something generic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Brave fingerprinting protection: noise for pixels, one name for the GPU
&lt;/h2&gt;

&lt;p&gt;Brave calls its noise farbling. Canvas readback, Web Audio output and WebGL values come back slightly altered, by an amount nobody notices on screen. The noise comes from a seed that is new every session and different for every site. Inside one site and one session the answers stay consistent, so pages keep working; across sites and across restarts they don't match. An embedded tracker doesn't get a seed of its own. It inherits the one of the page it sits on, so the same tracker reads different values on two sites and can't join the visits. Fingerprinting scripts typically hash many values into one ID, so changing a single input changes the whole hash.&lt;/p&gt;

&lt;p&gt;For names, Brave blends in. In version 1.93, rolled out from August 2026 on desktop and Android, the WebGL vendor and renderer strings both come back as "Brave", the WebGPU adapter details are emptied, and the list of supported WebGL extensions gets noise, because that list differs by GPU and driver. Every Brave user presents the same graphics card, which makes a crowd, though the string also tells a site which browser it is talking to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Firefox and Safari fingerprinting protection: some noise, some lists
&lt;/h2&gt;

&lt;p&gt;Since Firefox 151 (May 2026), desktop Firefox changes the canvas image a script exports, differently in each browsing session, in every window. Its standard tracking protection also blocks the known fingerprinters. Private windows and Strict mode add more, including a coarse CPU core count. The pixel noise they are meant to add on top doesn't currently run next to the lighter mode, so a script that reads canvas pixels directly still gets the real ones. Tor-style uniformity (the resistFingerprinting preference) is an advanced setting, off by default.&lt;/p&gt;

&lt;p&gt;Safari takes two routes. In Private Browsing it adds tiny noise to 2D canvas and WebGL readback and to Web Audio samples, and it reports the screen as the same size as the window; the same set can be turned on for every tab in Advanced settings. In normal windows, since Safari 26 (September 2025), known fingerprinting scripts can't reliably read screen size, CPU core count, speech voices, audio or 2D canvas, and can't store long-lived data. That layer works from a list; a script that isn't on it still reads a normal window.&lt;/p&gt;

&lt;h2&gt;
  
  
  Browser fingerprinting protection compared
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Browser&lt;/th&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;What it changes&lt;/th&gt;
&lt;th&gt;The catch&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Brave&lt;/td&gt;
&lt;td&gt;Randomize, plus one shared GPU name&lt;/td&gt;
&lt;td&gt;Canvas, audio and WebGL values shift per site and session; GPU strings read "Brave"&lt;/td&gt;
&lt;td&gt;Noise is best-effort&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Firefox&lt;/td&gt;
&lt;td&gt;Block, light randomization&lt;/td&gt;
&lt;td&gt;Known fingerprinters blocked; exported canvas varies per session; private windows and Strict add a coarse core count&lt;/td&gt;
&lt;td&gt;Pixels read directly stay real; uniform mode is off by default&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Safari&lt;/td&gt;
&lt;td&gt;Block, noise&lt;/td&gt;
&lt;td&gt;Known scripts restricted in every window; noise on canvas, WebGL and audio in private windows&lt;/td&gt;
&lt;td&gt;A script not on the list still reads normal windows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tor Browser&lt;/td&gt;
&lt;td&gt;Blend in&lt;/td&gt;
&lt;td&gt;One user agent per OS family, window letterboxing, canvas extraction blocked&lt;/td&gt;
&lt;td&gt;Users are grouped into fewer buckets, not made identical&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mullvad Browser&lt;/td&gt;
&lt;td&gt;Blend in&lt;/td&gt;
&lt;td&gt;Same techniques, no Tor network&lt;/td&gt;
&lt;td&gt;Your IP stays visible without a VPN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LibreWolf&lt;/td&gt;
&lt;td&gt;Blend in&lt;/td&gt;
&lt;td&gt;resistFingerprinting on, WebGL off, language reported as en-US&lt;/td&gt;
&lt;td&gt;The crowd is LibreWolf users only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DuckDuckGo&lt;/td&gt;
&lt;td&gt;Block&lt;/td&gt;
&lt;td&gt;Listed fingerprinting scripts blocked, listed APIs overridden&lt;/td&gt;
&lt;td&gt;Covers what is on its lists&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Edge&lt;/td&gt;
&lt;td&gt;Block&lt;/td&gt;
&lt;td&gt;Fingerprinters that also sit on another tracker list, at every level&lt;/td&gt;
&lt;td&gt;Scripts only on the fingerprinting list still run&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chrome&lt;/td&gt;
&lt;td&gt;Reduced User-Agent only&lt;/td&gt;
&lt;td&gt;Less detail in the User-Agent string; canvas, GPU and audio values stay real&lt;/td&gt;
&lt;td&gt;Incognito doesn't change that&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opera, Vivaldi&lt;/td&gt;
&lt;td&gt;Tracker-blocker lists&lt;/td&gt;
&lt;td&gt;Known trackers blocked&lt;/td&gt;
&lt;td&gt;No fingerprint-specific protection documented&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The table covers one question. What each browser also blocks, sends home, hides with a built-in VPN or does with AI is in the &lt;a href="https://packet.guru/blog/best-browser-for-privacy" rel="noopener noreferrer"&gt;full comparison of 11 browsers&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  When protection makes you stand out
&lt;/h2&gt;

&lt;p&gt;Blending in works only where the crowd is big. A US English setting is common on most sites, yet on a small foreign-language site the same setting can single you out, and a browser can't know how many visitors resemble you on each site.&lt;/p&gt;

&lt;p&gt;The same logic punishes rare setups. Brave dropped its Strict fingerprinting mode: it broke sites, and fewer than 0.5% of users ran it, a group small enough to stand out. Tor Browser doesn't let you choose which operating system you appear as, because any choice would make users more unique. Changing many settings, or stacking extensions that rewrite values, tends to make a browser rarer, not more private.&lt;/p&gt;

&lt;p&gt;Randomization has the opposite limit. It is a best-effort defense against trackers working at web scale, and a determined attacker aiming at one person can try to filter the noise out.&lt;/p&gt;

&lt;h2&gt;
  
  
  What incognito and a VPN leave alone
&lt;/h2&gt;

&lt;p&gt;A private window in Chrome leaves canvas and GPU values as they are. In Firefox and Safari it switches on the extra protections above. A VPN swaps the IP address and leaves every value measured inside the browser untouched. Below the browser, the first TCP packet still shows the operating system's network stack, whatever the user agent claims, and no browser setting edits it.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to check what your browser really does
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open the &lt;a href="https://packet.guru/whoami" rel="noopener noreferrer"&gt;Privacy &amp;amp; Trust Index&lt;/a&gt; and let the scan finish. Note the result on the Canvas Fingerprint card and the WebGL renderer under Graphics &amp;amp; Media Fingerprint. A stable canvas hash is shown there too.&lt;/li&gt;
&lt;li&gt;Close and reopen the browser, or use a private window, and scan again. A hash that changed is being randomized. One that stayed the same is a stable ID.&lt;/li&gt;
&lt;li&gt;Read the card. CANVAS LEAK means the drawing was identical every time and lowers the Privacy score. IDENTITY SHIFTING means it changed between reads, PROTECTED means light noise, CANVAS INTERCEPTED means a tool is handling it, CANVAS BLOCKED means the canvas is off. None of the five results lowers the Trust score.&lt;/li&gt;
&lt;li&gt;Read the renderer string. A generic or empty value is protection; a string that names your actual GPU is public to every page.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A single scan can't measure how rare you are, because rarity depends on who else visits. The &lt;a href="https://packet.guru/blog/canvas-leak" rel="noopener noreferrer"&gt;canvas leak guide&lt;/a&gt; explains each result and how the browsers above draw the line.&lt;/p&gt;

</description>
      <category>security</category>
      <category>privacy</category>
      <category>browser</category>
      <category>fingerprint</category>
    </item>
    <item>
      <title>How to Identify AI Agents When Anyone Can Fake the User-Agent</title>
      <dc:creator>ParallaxGrain</dc:creator>
      <pubDate>Thu, 29 Oct 2026 14:00:00 +0000</pubDate>
      <link>https://dev.to/parallaxgrain/how-to-identify-ai-agents-when-anyone-can-fake-the-user-agent-2o3l</link>
      <guid>https://dev.to/parallaxgrain/how-to-identify-ai-agents-when-anyone-can-fake-the-user-agent-2o3l</guid>
      <description>&lt;p&gt;Your access log says ChatGPT. Or Claude, or Google-Agent. The line looks official, but the name in it is whatever the client chose to send, and any scraper can send the same one.&lt;/p&gt;

&lt;p&gt;That used to be a headache for search engines and big publishers. Now AI agents compare prices and fill carts for real people, and every site with a firewall rule or a rate limit runs into it. Knowing how to identify AI agents comes down to one question: who sent this request, and can they prove it?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A User-Agent is what a bot says about itself. A signature is something it has to prove, with a key an impostor doesn't have.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why AI agents are harder to identify than crawlers
&lt;/h2&gt;

&lt;p&gt;Classic crawlers are the easy case. Googlebot crawls from Google's own addresses, and those addresses have hostnames that point back to Google. Agents break that pattern in three ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They act for a person, in real time. An agent opens a page because someone asked it to, and for user-triggered fetchers like ChatGPT-User, robots.txt rules may not apply.&lt;/li&gt;
&lt;li&gt;They often drive a real browser. The request looks like Chrome from the TLS handshake to the last header, so the tricks that catch simple scripts see a browser.&lt;/li&gt;
&lt;li&gt;They run on shared infrastructure. Plenty of agents work inside cloud browsers hosted by third-party platforms, so the IP address belongs to the platform and every other customer exits from the same pool.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The old ways to detect AI agents either can't see the agent at all, or can't tell it apart from an impostor on the same network.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four ways to check a bot's identity, and what each can fake
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;What it checks&lt;/th&gt;
&lt;th&gt;Can an impostor fake it?&lt;/th&gt;
&lt;th&gt;Works for agents on shared clouds?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;User-Agent string&lt;/td&gt;
&lt;td&gt;Text the client writes about itself&lt;/td&gt;
&lt;td&gt;Yes, in seconds&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Published IP ranges&lt;/td&gt;
&lt;td&gt;The address is on the operator's list&lt;/td&gt;
&lt;td&gt;Not from outside, but co-tenants on those IPs look identical&lt;/td&gt;
&lt;td&gt;Poorly: the list names the platform, not the agent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reverse DNS&lt;/td&gt;
&lt;td&gt;The IP's hostname is the operator's and resolves back to it&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Rarely: mostly search crawlers set this up&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Signed request (Web Bot Auth)&lt;/td&gt;
&lt;td&gt;A key published on the operator's domain signed the request&lt;/td&gt;
&lt;td&gt;Not without the private key&lt;/td&gt;
&lt;td&gt;Yes: the key travels with the agent&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The forward half of the reverse DNS check is the part that matters. Anyone can set the reverse name of their own IP to googlebot.com, but only Google can make that name resolve back to it.&lt;/p&gt;

&lt;p&gt;The first three methods infer identity from something next to the request: a string inside it, the address behind it, a DNS record somewhere else. A signature puts the proof inside the request itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  How signed requests work
&lt;/h2&gt;

&lt;p&gt;Web Bot Auth is built on HTTP Message Signatures, RFC 9421, a finished IETF standard since February 2024. The part that tells bots how to use it is still a set of drafts in an IETF working group, so details can change. The flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The operator creates a key pair. In practice that's Ed25519, a small, fast elliptic-curve key. The private half stays with the operator.&lt;/li&gt;
&lt;li&gt;It publishes the public half in a key directory: a small JSON file at a fixed address on its own domain, /.well-known/http-message-signatures-directory. The file is served over HTTPS, so the domain's TLS certificate vouches for who published those keys.&lt;/li&gt;
&lt;li&gt;The agent adds three headers to every request. Signature-Agent says where its keys live. Signature-Input lists what was signed: at least the host being requested, plus a creation time, an expiry time, the key's ID and the tag web-bot-auth, which marks it as a bot signature. Signature carries the signature itself.&lt;/li&gt;
&lt;li&gt;The site checks. It reads Signature-Agent, fetches the directory (once, then from cache, even for an agent it has never seen), picks the key by its ID, rebuilds the signed text from the request and verifies the signature. With the keys cached, that's one signature check per request.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Two details make this hard to abuse. The signature covers the host, so a copy captured on one site won't verify on another. And it expires. The drafts recommend a lifetime of no more than 24 hours, so a stolen copy goes stale on its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a valid signature proves, and what it doesn't
&lt;/h2&gt;

&lt;p&gt;A valid signature tells you two things: the request was signed by someone holding a key that the domain in Signature-Agent publishes, and it was signed inside its validity window.&lt;/p&gt;

&lt;p&gt;It doesn't tell you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;that the agent is harmless, or allowed to do what it's doing. Good bot vs bad bot is still your call, made on behavior;&lt;/li&gt;
&lt;li&gt;that the request is fresh. A copied signature can be replayed until it expires, unless the site also demands a one-time value (a nonce) and remembers the ones it has seen;&lt;/li&gt;
&lt;li&gt;who the human behind the agent is. The protocol doesn't authenticate users at all.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A missing signature proves nothing either. Your own browser doesn't sign requests, and neither does most legitimate software.&lt;/p&gt;

&lt;p&gt;One rule follows from all of this. Attach your policy to the domain whose key verified the request, never to whatever the Signature-Agent header says. The header only tells you where to look for the key.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who signs today, and who checks
&lt;/h2&gt;

&lt;p&gt;Adoption is early, and it changes month to month:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The cloud browser behind ChatGPT's agent features signs its outbound requests, with Signature-Agent set to chatgpt.com.&lt;/li&gt;
&lt;li&gt;Google signs some Google-Agent requests, as agent.bot.goog. The rollout is experimental and partial, so IP and reverse DNS checks stay as the fallback.&lt;/li&gt;
&lt;li&gt;Classic crawlers such as GPTBot are still verified by their published IP lists.&lt;/li&gt;
&lt;li&gt;On the checking side, Cloudflare, AWS WAF, Akamai and Vercel verify these signatures for their customers. Cloudflare accepts a valid signature as one of three ways a verified bot can identify itself, next to an IP list and reverse DNS.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to identify AI agents on your site
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Stop letting the User-Agent open doors on its own. A rule that waves through anything calling itself ChatGPT waves through every scraper that copies the name, and faking a User-Agent takes one line of config.&lt;/li&gt;
&lt;li&gt;Check what your CDN or WAF already does. Behind one of the services above, signed agents may already be verified and labeled for you. Point your rules at that label, not at the string.&lt;/li&gt;
&lt;li&gt;Log the three signature headers. Default access log formats skip them, and without them you can't check a request after the fact.&lt;/li&gt;
&lt;li&gt;Keep IP lists and reverse DNS for everything that doesn't sign, and refresh the lists on a schedule.&lt;/li&gt;
&lt;li&gt;Sort requests into three groups: verified (policy goes to the signing domain), signed but failed (suspicious, often just a misconfigured client) and unsigned (unknown, which is different from guilty).&lt;/li&gt;
&lt;li&gt;Keep your rate limits. A verified agent hitting your search endpoint 50 times a second is still hitting it 50 times a second.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To see what a real signed request proves, paste one, headers included, into the &lt;a href="https://packet.guru/agents" rel="noopener noreferrer"&gt;Agent Verifier&lt;/a&gt;. It shows what the signature proved and what the key directory publishes, and when something fails, it names the fault and the one change that fixes it. Nothing is stored, and an expired signature works too, checked as of the moment it was made.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you build agents: sign, then check from the outside
&lt;/h2&gt;

&lt;p&gt;On rented cloud IPs, a signature is the one identity signal that doesn't depend on the neighbors. The catch is that a broken one fails silently. From the client side, a malformed signature looks exactly like an agent the site has never heard of. The usual suspects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;signed text built one character differently from what the verifier rebuilds, like missing quotes or an extra line break;&lt;/li&gt;
&lt;li&gt;a key directory your own CDN refuses to serve, because a bot rule blocks the verifier;&lt;/li&gt;
&lt;li&gt;a key ID that's a short label instead of the key's thumbprint;&lt;/li&gt;
&lt;li&gt;a redirect between the bare domain and www, which verifiers following the draft won't follow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All four look fine from your own machine. Paste a request your agent really sent into the Agent Verifier to see which one you hit, or follow the &lt;a href="https://packet.guru/agents/guide" rel="noopener noreferrer"&gt;implementation guide&lt;/a&gt; step by step: key, directory, signature, check. Your agent can also check itself. Connect the &lt;a href="https://packet.guru/agents/mcp" rel="noopener noreferrer"&gt;packet.guru MCP server&lt;/a&gt; and it finds a self-check tool that takes no arguments and reports how its own request arrives, signed or not.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>security</category>
      <category>agents</category>
    </item>
    <item>
      <title>What a VPN Doesn't Hide: 4 Things Websites Still See</title>
      <dc:creator>ParallaxGrain</dc:creator>
      <pubDate>Tue, 27 Oct 2026 14:00:00 +0000</pubDate>
      <link>https://dev.to/parallaxgrain/what-a-vpn-doesnt-hide-4-things-websites-still-see-5157</link>
      <guid>https://dev.to/parallaxgrain/what-a-vpn-doesnt-hide-4-things-websites-still-see-5157</guid>
      <description>&lt;p&gt;A VPN does one job, and does it well. It wraps your traffic in an encrypted tunnel to its own server. Your Wi-Fi and your internet provider see only a connection to that server, and websites see the server's IP address instead of yours.&lt;/p&gt;

&lt;p&gt;That's the whole job. What a VPN doesn't hide is everything your device says about itself on the way in, plus anything that slips around the tunnel. You can be tracked with a VPN on, and a site can often work out roughly where you really are.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A VPN changes where your traffic comes from. It doesn't change what your device says about itself.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What a VPN doesn't hide, at a glance
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What a website sees&lt;/th&gt;
&lt;th&gt;VPN off&lt;/th&gt;
&lt;th&gt;VPN on&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;IP address&lt;/td&gt;
&lt;td&gt;Your provider's&lt;/td&gt;
&lt;td&gt;The VPN server's&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Location from the IP&lt;/td&gt;
&lt;td&gt;Your city or region&lt;/td&gt;
&lt;td&gt;The server's country&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DNS resolver&lt;/td&gt;
&lt;td&gt;Your provider's&lt;/td&gt;
&lt;td&gt;The VPN's, unless DNS leaks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Address found by WebRTC&lt;/td&gt;
&lt;td&gt;Yours&lt;/td&gt;
&lt;td&gt;The VPN's, unless it leaks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Time zone and languages&lt;/td&gt;
&lt;td&gt;Yours&lt;/td&gt;
&lt;td&gt;Still yours&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Browser fingerprint&lt;/td&gt;
&lt;td&gt;Yours&lt;/td&gt;
&lt;td&gt;Still yours&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cookies and logged-in accounts&lt;/td&gt;
&lt;td&gt;Yours&lt;/td&gt;
&lt;td&gt;Still yours&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The first two rows are what you pay for. The rest is where people get caught.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Your DNS lookups
&lt;/h2&gt;

&lt;p&gt;Before your browser opens a site, it asks for the site's numeric address. That lookup is DNS, the internet's phone book, and the server that answers is a resolver. A VPN should route these questions to its own resolver, inside the tunnel. When they go to your provider's resolver instead, that's a DNS leak: your provider sees the name of every site you open, and any site that checks sees your lookups and your connection coming from two different networks.&lt;/p&gt;

&lt;p&gt;Sites spot it with a neat trick: the page makes your browser look up a random, never-used name under a domain the site controls. No resolver has it cached, so the question travels all the way to the site's own name server, which records who asked. Your home provider's resolver next to a VPN's IP means the leak is real.&lt;/p&gt;

&lt;p&gt;The usual causes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the VPN app doesn't set its own DNS server;&lt;/li&gt;
&lt;li&gt;Windows, when a lookup times out, can resend it on every network interface, including the one outside the tunnel;&lt;/li&gt;
&lt;li&gt;your router hands out IPv6 DNS servers, and the VPN only tunnels IPv4.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most VPN apps have a DNS leak protection setting. Turn it on.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Your real IP, through WebRTC and IPv6
&lt;/h2&gt;

&lt;p&gt;WebRTC is the part of the browser behind video calls and direct file transfers. To connect two browsers directly, it asks a STUN server one question: what address do you see me coming from? The answer is your public IP, and a page can trigger the question without any permission prompt.&lt;/p&gt;

&lt;p&gt;With a full-tunnel VPN, the STUN server sees the VPN's address, and nothing new leaks. Your real address gets out in three setups:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A browser "VPN" extension. In Chrome and Firefox it works as a proxy, and unless the extension blocks it, WebRTC sends its STUN request over UDP, straight past the proxy.&lt;/li&gt;
&lt;li&gt;A split tunnel that lets the browser, or all UDP traffic, bypass the VPN.&lt;/li&gt;
&lt;li&gt;A VPN that only carries IPv4. If your provider also gives you IPv6, that traffic still goes out through your router, so any site you reach over IPv6 sees your real address, and WebRTC can list it next to the VPN's.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your local address, the 192.168.x.x kind, is mostly safe now: Chrome has replaced it with a random .local name since version 76, unless the site already has camera or microphone access.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Your clock and your languages
&lt;/h2&gt;

&lt;p&gt;Any page can read your device's time zone with one line of JavaScript, no permission needed. It comes back as a full zone name, like Europe/Warsaw or America/Chicago, which usually points to one country. The server looks up the time zone of your IP in a geolocation database and compares the two.&lt;/p&gt;

&lt;p&gt;A VPN can't touch this. The time zone is a setting on your device, and no VPN protocol carries or rewrites it. Your languages come along unchanged too: the browser lists them in the Accept-Language header, a line of metadata attached to every request.&lt;/p&gt;

&lt;p&gt;A laptop set to Europe/Warsaw, with Polish as its first language, behind an IP in a New York data center tells a site two things: the user is probably in Poland, and something sits in between. That's a &lt;a href="https://packet.guru/blog/time-mismatch-exposed" rel="noopener noreferrer"&gt;timezone mismatch&lt;/a&gt;. Travellers and company VPNs produce it every day, so on its own it rarely gets anyone blocked. Next to other warning signs, it can mean a CAPTCHA or an extra login check.&lt;/p&gt;

&lt;p&gt;The fix is boring: set your device's time zone to match the VPN server, or pick a server in your own time zone. Extensions that fake the zone tend to miss one of the several places a page can read it from, and a browser that reports two zones at once looks worse than an honest mismatch.&lt;/p&gt;

&lt;p&gt;This is also why a VPN often isn't hiding your location on maps and delivery sites. A site you've allowed to use your location gets it from the device itself, through GPS or the Wi-Fi networks around you, and a VPN changes neither.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Your browser fingerprint and your accounts
&lt;/h2&gt;

&lt;p&gt;Your browser describes itself to every site: screen size, installed fonts, graphics card, CPU cores, and the tiny differences in how your hardware draws an image on an invisible canvas. Together these values form a browser fingerprint, an ID that needs no cookies. Every value is measured on your device, so it stays the same when your IP changes.&lt;/p&gt;

&lt;p&gt;Stored data comes along too. Cookies set yesterday on your home connection are still in the browser today, and the moment you log in, the site knows exactly who you are, whatever country your IP is in.&lt;/p&gt;

&lt;p&gt;Does a VPN hide your identity, then, or make you anonymous? Not by itself. It hides your address from websites and your browsing from your provider. Your identity lives in the browser and in your accounts, and those don't change inside a tunnel.&lt;/p&gt;

&lt;p&gt;The same four things, in a YouTube Short:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/Nrvf26aFm8w" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  How websites detect a VPN anyway
&lt;/h2&gt;

&lt;p&gt;A VPN that leaks nothing is still usually easy to spot, because sites add up clues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The address. VPN servers usually run in data centers. Every IP belongs to a network with an ASN, the number that identifies who owns it, and IP databases label hosting networks and known VPN ranges.&lt;/li&gt;
&lt;li&gt;The first packet. A VPN forwards your device's own packets, so your operating system still shows through. That packet also states the maximum segment size (MSS), the largest chunk of data your device accepts at once. Tunnel headers eat into it, so the MSS comes out smaller than on a plain home line, in a range typical of tunnels.&lt;/li&gt;
&lt;li&gt;Proxies leave the opposite mark. A proxy opens its own connection to the site, so the site reads the proxy server's operating system instead of yours. A browser that says Windows over a packet that looks like Linux is the classic proxy pattern.&lt;/li&gt;
&lt;li&gt;Any of the four leaks above.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Detection tells a site that you use a VPN, not who you are. For a bank or a streaming service, that alone can be reason enough for an extra check or a block.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to check what your VPN leaves exposed
&lt;/h2&gt;

&lt;p&gt;The Privacy &amp;amp; Trust Index on packet.guru is a browser fingerprint test and a leak test in one. It shows what a website sees about your connection and your browser, card by card.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Turn the VPN off, open &lt;a href="https://packet.guru/whoami" rel="noopener noreferrer"&gt;packet.guru/whoami&lt;/a&gt; and let the scan finish.&lt;/li&gt;
&lt;li&gt;Turn the VPN on, reload the page and wait for the new scan.&lt;/li&gt;
&lt;li&gt;Compare the cards:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;IP Reputation&lt;/strong&gt; should switch to VPN / PROXY or DATACENTER, and Network Details should show no second address from your home provider.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DNS Privacy&lt;/strong&gt; should not say DNS LEAK.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WebRTC Status&lt;/strong&gt; should read SAFE or PUBLIC IP MATCH, not LEAK DETECTED.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regional Integrity&lt;/strong&gt; shows TIMEZONE MISMATCH if your clock still points home.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Read the two scores. Privacy is how hidden you are, Trust is how genuine you look to anti-fraud systems. A VPN can raise the first and lower the second.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The canvas, audio and speech-voice fingerprints usually come out the same in both runs. That's the part the VPN never touched.&lt;/p&gt;

&lt;p&gt;For the full set of checks, including a kill switch test for the moment your VPN drops, see the &lt;a href="https://packet.guru/blog/vpn-test" rel="noopener noreferrer"&gt;VPN test guide&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>privacy</category>
      <category>security</category>
      <category>networking</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How Websites Identify Your Device Without Cookies</title>
      <dc:creator>ParallaxGrain</dc:creator>
      <pubDate>Sun, 25 Oct 2026 19:30:35 +0000</pubDate>
      <link>https://dev.to/parallaxgrain/how-websites-identify-your-device-without-cookies-3i2e</link>
      <guid>https://dev.to/parallaxgrain/how-websites-identify-your-device-without-cookies-3i2e</guid>
      <description>&lt;p&gt;Clearing cookies feels like starting over. For a lot of sites it isn't. They never needed to store anything on your device to recognize you, because your browser describes itself in enough detail on every visit that the description works as an ID.&lt;/p&gt;

&lt;p&gt;This is browser fingerprinting, and it's how many websites identify your device without cookies.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A fingerprint isn't stored on your device. There is nothing to delete.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The three layers of a fingerprint
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd4aj91mrtwbcb8bahkjw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd4aj91mrtwbcb8bahkjw.png" alt="Three layers of a browser fingerprint: page scripts, request headers and the connection, combined into one device ID" width="799" height="491"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A fingerprint is built from three layers. Each one on its own says little. Together they point to one device.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;th&gt;What it reveals&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Connection&lt;/td&gt;
&lt;td&gt;IP address&lt;/td&gt;
&lt;td&gt;Your provider and rough location&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Connection&lt;/td&gt;
&lt;td&gt;TLS handshake (JA4)&lt;/td&gt;
&lt;td&gt;Which browser or tool really connected&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Connection&lt;/td&gt;
&lt;td&gt;First TCP packet&lt;/td&gt;
&lt;td&gt;Your operating system family&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Headers&lt;/td&gt;
&lt;td&gt;User-Agent&lt;/td&gt;
&lt;td&gt;Browser, version and OS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Headers&lt;/td&gt;
&lt;td&gt;Accept-Language&lt;/td&gt;
&lt;td&gt;Your preferred languages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Headers&lt;/td&gt;
&lt;td&gt;Client hints (Chromium)&lt;/td&gt;
&lt;td&gt;Exact build, CPU architecture, phone model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Script&lt;/td&gt;
&lt;td&gt;Screen&lt;/td&gt;
&lt;td&gt;Resolution, pixel density, taskbar size&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Script&lt;/td&gt;
&lt;td&gt;Time zone&lt;/td&gt;
&lt;td&gt;Your region, checked against your IP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Script&lt;/td&gt;
&lt;td&gt;Fonts&lt;/td&gt;
&lt;td&gt;Software you have installed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Script&lt;/td&gt;
&lt;td&gt;WebGL&lt;/td&gt;
&lt;td&gt;Your graphics card model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Script&lt;/td&gt;
&lt;td&gt;Canvas and audio&lt;/td&gt;
&lt;td&gt;How your hardware draws images and processes sound&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Script&lt;/td&gt;
&lt;td&gt;Hardware&lt;/td&gt;
&lt;td&gt;CPU cores, memory, touch support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Script&lt;/td&gt;
&lt;td&gt;Speech voices&lt;/td&gt;
&lt;td&gt;Your OS and language packs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What your browser tells every website
&lt;/h2&gt;

&lt;p&gt;The header layer arrives with every request, before any script on the page runs. Your browser sends its User-Agent, a short line of text with the browser name, version and operating system, and its language preferences. Chrome and other Chromium browsers add client hints on request, down to the exact build and, on Android, the phone model.&lt;/p&gt;

&lt;p&gt;This is passive fingerprinting. The site only has to write down what your browser already sends.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a script on the page can measure
&lt;/h2&gt;

&lt;p&gt;Active fingerprinting goes further. A script asks the browser questions, and the browser answers, because ordinary websites need the same answers to work. A few examples show how much leaks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The gap between your full screen and the usable area gives away the size of your taskbar or dock.&lt;/li&gt;
&lt;li&gt;Your time zone gets compared with your IP address. A browser set to Tokyo time behind a German IP is unusual, and unusual is exactly what trackers and fraud systems look for.&lt;/li&gt;
&lt;li&gt;A page can't ask for a list of your fonts, so it tries a few hundred font names and measures how wide the text comes out. Office suites and design apps install fonts most people don't have.&lt;/li&gt;
&lt;li&gt;Through WebGL, the part of the browser that draws 3D graphics, a page can usually read the exact GPU model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The strongest signal is the way your computer draws. In canvas fingerprinting, the page draws text and shapes on an invisible canvas and reads the pixels back. The result depends on your operating system, fonts, graphics driver and GPU, so the same machine produces the same image every time, down to the pixel. Audio works the same way: a short sound is processed inside the browser with nothing played out loud, and tiny differences in the result are measured.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the combination identifies you
&lt;/h2&gt;

&lt;p&gt;Hardly any of these values is rare on its own. Millions of people run Chrome on Windows with English settings and a 1920×1080 screen. Add the time zone, the fonts, the GPU and the canvas result, and that crowd shrinks fast.&lt;/p&gt;

&lt;p&gt;A tracker needs exactly two things from the combination:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Distinctive.&lt;/strong&gt; Few other browsers share it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stable.&lt;/strong&gt; It stays the same between visits.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Stability doesn't have to be perfect. When a browser update changes a couple of values, the rest stay put, and the new fingerprint is easy to match to the old one. Most defenses are built on the opposite idea: a value that changes on every visit is useless for tracking, however rare it is.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fingerprints below the browser
&lt;/h2&gt;

&lt;p&gt;The connection layer is the one most people never hear about. When your browser opens an HTTPS connection, its very first message lists the encryption methods it supports. A format called JA4 turns that list into a short code that looks different for Chrome, Firefox, Safari and a Python script. One layer lower, the first network packet carries values set by your operating system, which point to Windows, macOS, Linux or iOS regardless of what the browser says.&lt;/p&gt;

&lt;p&gt;No browser setting changes either one. Servers compare both with what the browser claims to be, so an "iPhone" that connects with the handshake of a Python script stands out right away.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real visitor vs. headless bot
&lt;/h2&gt;

&lt;p&gt;Bot detection relies on exactly these checks. Here is how an ordinary laptop compares with a headless Chrome running on a server, the kind scrapers use:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;th&gt;Ordinary laptop&lt;/th&gt;
&lt;th&gt;Headless Chrome on a server&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;User-Agent&lt;/td&gt;
&lt;td&gt;Chrome on Windows or macOS&lt;/td&gt;
&lt;td&gt;Contains "HeadlessChrome"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Screen&lt;/td&gt;
&lt;td&gt;1920×1080 with a taskbar&lt;/td&gt;
&lt;td&gt;800×600, no taskbar&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Graphics card&lt;/td&gt;
&lt;td&gt;Intel, AMD, NVIDIA or Apple&lt;/td&gt;
&lt;td&gt;SwiftShader, a software renderer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Speech voices&lt;/td&gt;
&lt;td&gt;Several system voices&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IP address&lt;/td&gt;
&lt;td&gt;Home or mobile provider&lt;/td&gt;
&lt;td&gt;Datacenter&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And this is what the packet.guru scan reports for that headless Chrome:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flz8urkkn6p8h049pzd01.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flz8urkkn6p8h049pzd01.png" alt="packet.guru Privacy and Trust Index for a headless Chrome on a server: Privacy 60, Trust 45, bot detected, datacenter IP, timezone mismatch" width="800" height="941"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Trust drops to 45 out of 100: automation detected, a datacenter IP, and a clock that doesn't match the IP's region. The TLS and TCP fingerprints pass, because this really is Chrome on Linux. That's the point. These systems care less about how unique you are than about whether your details agree with each other.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who uses fingerprinting
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Banks and online shops&lt;/strong&gt;, against account takeover. A correct password typed on a device they have never seen can trigger an extra check.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bot detection&lt;/strong&gt;, to catch automated browsers like the one above.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Advertising&lt;/strong&gt;, to link your visits across sites even when you block or delete cookies. Since February 2025, Google no longer forbids advertisers who use its ad products from fingerprinting, so expect more of it. In the EU, fingerprinting for ads and tracking needs your consent, the same as cookies.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What doesn't protect you
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What people try&lt;/th&gt;
&lt;th&gt;What it changes&lt;/th&gt;
&lt;th&gt;Your fingerprint&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Clearing cookies&lt;/td&gt;
&lt;td&gt;Removes stored identifiers&lt;/td&gt;
&lt;td&gt;Unchanged&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VPN&lt;/td&gt;
&lt;td&gt;Your IP address&lt;/td&gt;
&lt;td&gt;Unchanged, and a badly configured VPN can &lt;a href="https://packet.guru/blog/vpn-test" rel="noopener noreferrer"&gt;leak your real IP&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Incognito mode&lt;/td&gt;
&lt;td&gt;What gets saved on your device&lt;/td&gt;
&lt;td&gt;Mostly unchanged&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;More privacy extensions&lt;/td&gt;
&lt;td&gt;A few values here and there&lt;/td&gt;
&lt;td&gt;Often more unique&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Extensions deserve a closer look. Every extension that changes what pages see is a trait of its own, and changing one value while leaving the rest creates contradictions, like a Windows User-Agent on top of a Mac's graphics hardware. To a fraud system that looks like forgery.&lt;/p&gt;

&lt;p&gt;Incognito is the most common false hope. Here's the short version:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/q6rG_QhSXd4" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  How to avoid browser fingerprinting
&lt;/h2&gt;

&lt;p&gt;The best choice is a browser with protection built in, used with its default settings.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Browser&lt;/th&gt;
&lt;th&gt;How it protects you&lt;/th&gt;
&lt;th&gt;Trade-off&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Tor Browser&lt;/td&gt;
&lt;td&gt;Makes all users look alike&lt;/td&gt;
&lt;td&gt;Strongest, but slower and some sites break&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Brave&lt;/td&gt;
&lt;td&gt;Random changes to canvas, WebGL and audio, per site and session&lt;/td&gt;
&lt;td&gt;On by default&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Safari&lt;/td&gt;
&lt;td&gt;Random changes to canvas, WebGL and audio&lt;/td&gt;
&lt;td&gt;Strongest in private browsing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Firefox&lt;/td&gt;
&lt;td&gt;Blocks known fingerprinting scripts, limits more values&lt;/td&gt;
&lt;td&gt;Full protection in private windows and strict mode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chrome&lt;/td&gt;
&lt;td&gt;Blocks known fingerprinting scripts in Incognito&lt;/td&gt;
&lt;td&gt;Little protection in regular windows&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Whatever you use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;keep extensions to a minimum;&lt;/li&gt;
&lt;li&gt;don't change your User-Agent by hand;&lt;/li&gt;
&lt;li&gt;switch protection off only for the one site that breaks, not globally.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Check your browser in two minutes
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;a href="https://packet.guru/whoami" rel="noopener noreferrer"&gt;packet.guru/whoami&lt;/a&gt; and run the scan.&lt;/li&gt;
&lt;li&gt;Look at the two scores: Privacy, how hidden you are, and Trust, how genuine you look to a fraud system. The cards below show the reason behind every point.&lt;/li&gt;
&lt;li&gt;Open a private window or restart the browser, and scan again.&lt;/li&gt;
&lt;li&gt;Compare. Values that changed between the two runs are being randomized. Values that stayed the same can be used to recognize you.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Browser-by-browser defenses are covered in the &lt;a href="https://packet.guru/blog/what-is-a-browser-fingerprint" rel="noopener noreferrer"&gt;guide to browser fingerprinting&lt;/a&gt; on the packet.guru blog.&lt;/p&gt;

</description>
      <category>privacy</category>
      <category>security</category>
      <category>browser</category>
      <category>fingerprint</category>
    </item>
  </channel>
</rss>
