Websites use various methods to identify and track users, including header replication, browser activity mimicking, IP reputation, and TLS fingerprinting. While many of us are familiar with the first three, TLS fingerprinting is a lesser-known but powerful technique.

What is TLS Fingerprinting?

During the HTTPS handshake, your browser sends specific details about its security capabilities, such as the cipher suites and extensions it supports. These details can be unique to your browser and device.

TLS fingerprinting is like taking a snapshot of these unique details to create a "fingerprint" of your device. This fingerprint can be used to identify and track your device across different websites.

A TLS fingerprint is often stored as a string or hashed string and is called "JA3" or "JA4," the newer version. JA3 focuses on the client's TLS parameters, while JA4 includes server-side parameters as well.

How to Spoof the TLS Fingerprint?

Fortunately, developers have created ways to bypass and spoof the TLS fingerprint. Here are some of my favorite libraries for doing so:

  • gospider007/requests: A Golang library to mimic different TLS fingerprints (Chrome, Safari, iOS, Android, etc.). It’s our favorite, and we use it internally! It also offers many other spoofing options.

  • 0x676e67/rquest: A Rust library that allows changing TLS fingerprints. It's very efficient, but it does not support JA3 and JA4 strings. This means if you need a custom fingerprint, you’ll have to build the cipher suite and other details yourself.

  • lexiforest/curl_cffi: A Python library using a forked cURL and OpenSSL library. It’s very efficient since it uses C-bindings. We also use it internally for some other projects.

Here is an example of our code using the Golang library:

var JA3 = strings.Join([]string{
	"771",
	"4865-4866-4867-49495-49199-42196-49200-52393-52392-49162-49172-49161-49181-156-151-47-53",
	"0-23-65281-10-11-35-13-51-45-43",
	"29-23-24",
	"0",
}, ",")

var spec ja3.Spec

func init() {
	ja3, err := ja3.CreateSpecWithStr(JA3)
	if err != nil {
		panic(err)
	}

	spec = ja3
}

func MakeRequest() ([]map[string]any, error) {
	response, err := requests.Get(context.TODO(), "https://tls.peet.ws/api/all", requests.RequestOption{
		ClientOption: requests.ClientOption{
			Ja3Spec:    spec,
			ForceHttp1: true,
			TlsConfig: &tls.Config{
				InsecureSkipVerify: true,
				MinVersion:         tls.VersionTLS12,
				MaxVersion:         tls.VersionTLS13,
			},
			Proxy:     GetProxy(),
		},
	})
	if err != nil {
		return nil, err
	}

	var json map[string]any
	if _, err := response.Json(&json); err != nil {
		return nil, err
	}

	return json, nil
}

It's really easy to use, especially if you use the built-in fingerprint profiles. In this case, we replicate a TLS fingerprint captured from a mobile phone, which explains why we use a custom JA3.

This also gives me a chance to introduce https://tls.peet.ws. This website is very helpful as it shows every detail of TLS fingerprinting and offers a great API.

Don’t Randomize TLS Fingerprint!

I wanted to discuss a common mistake: randomizing the TLS fingerprint. This doesn't make sense because most websites using TLS for bot detection rely on a whitelist, not a blacklist. For example, Google has a mobile app called "Google Search." This app might have its own TLS fingerprint, which could vary slightly depending on the device version and compatibility. However, it wouldn't make sense for Google to block an entire TLS fingerprint since real users might use it. Randomizing the fingerprint could create profiles that don’t exist in reality, and if you look at the source code of the library I mentioned above, most profiles are quite similar. A TLS fingerprint isn’t as unique as a JS/browser fingerprint can be.

For example, MacOS devices running version Sequoia 15 with Safari 18 will have the exact same fingerprint. They use the same hardware and similar versions, so the TLS will be the same.

This is well explained by curl-cffi: https://curl-cffi.readthedocs.io/en/latest/impersonate.html#should-i-randomize-my-fingerprints-for-each-request

However, randomizing the TLS profile (not its creation) might be useful in some situations. For example, if you recorded requests made by the same app on both Android and iOS devices, your script could sometimes use the Android profile (with matching headers) and other times use the iOS profile. This method can avoid some bans.

Questions & Answers

Before closing out, I wanted to make a small Q&A with frequent questions about TLS fingerprint and some misconceptions.

Can a proxy or a VPN change my TLS fingerprint?

Theoretically, no. When you make a plain HTTP request, the proxy can see all the details because it's not using a secure protocol. However, with an HTTPS request, a good proxy should just send your request through a raw TCP socket, so it doesn't change your original request or fingerprint. AltV6 Proxies do not change your fingerprint, which was an important consideration for us when developing our server.

How to capture the TLS fingerprint from a mobile phone?

We recommend using Proxyman. It will help you gather the cipher suite used along with other details. You can also redirect requests using the “Map Remote” feature to the API we mentioned earlier, allowing you to get the JA3 and JA4 strings instantly. This method has worked many times for us.

Are there other identification methods besides TLS fingerprinting?

Yes, unfortunately! With HTTP/2 and now HTTP/3, there are new specific details about the browser and device making the requests that a bot-protection company can capture to create a fingerprint of you. Fortunately, some libraries, including the Golang library, can already spoof those values.

Future Trends in TLS Fingerprinting

As technology advances, so do the methods used for tracking and identification. Future trends in TLS fingerprinting may include more advanced fingerprinting techniques that consider additional parameters. Staying updated with the latest research and developments is crucial to maintaining your privacy.

Conclusion

TLS fingerprinting is a powerful technique used to identify and track devices across the internet. By understanding how TLS fingerprinting works and employing techniques to spoof or impersonate fingerprints, you can enhance your online privacy and avoid being tracked. However, it's important to avoid randomizing your TLS fingerprint, as this can make your device more conspicuous or just not compatible. Instead, focus on mimicking the fingerprints of common devices to blend in with the crowd.

By following these guidelines, you can take control of your online privacy and protect yourself from unwanted tracking. Stay informed about the latest developments in TLS fingerprinting and adapt your strategies accordingly to maintain your digital anonymity.