HAProxy - JA4 TLS Client-Fingerprint - Lua Plugin

February 27, 2026 ยท View on GitHub


You need to run HAProxy 3.1 or higher to use this plugin!

If the needed features are not yet available in your version - it will fail with the error attempt to call a nil value (method 'ssl_fc_supported_versions_bin')

Note: The HAProxy enterprise-edition has native JA4-support that will provide you better performance.

Test it: fingerprint.oxl.app


Intro

About JA4:

About JA3:

Browser Fingerprinting:


Usage

  • Add the LUA script ja4.lua to your system

Config

  • Enable SSL/TLS capture with the global setting tune.ssl.capture-buffer-size 192
  • Load the LUA module by adding lua-load /etc/haproxy/lua/ja4.lua in the global section
  • Execute the LUA script on HTTP requests: http-request lua.fingerprint_ja4
  • Log the fingerprint: http-request capture var(txn.fingerprint_ja4) len 36

JA4 Database

You can use the DB to MAP script to create a HAProxy Mapfile from the FoxIO JA4-Database:

WARNING: The exact versions of client-applications may vary.

# download the database
curl -s https://ja4db.com/api/read/ -o ja4db.json

# build the map-file
python3 ja4db-dedupe.py
python3 ja4db-to-map.py

# examples:
> t13d1517h2_8daaf6152771_b0da82dd1658 Mozilla/5.0_(Windows_NT_10.0;_Win64;_x64)_AppleWebKit/537.36_(KHTML,_like_Gecko)_Chrome/125.0.0.0_Safari/537.36
> t13d1516h2_8daaf6152771_02713d6af862 Chromium_Browser

You can enable lookups like this: http-request set-var(txn.fingerprint_app) var(txn.fingerprint_ja4),map(/tmp/haproxy_ja4.map)

And log the results like this: http-request capture var(txn.fingerprint_app) len 200


License

This script is licensed under the MIT-license and thus is free to use.

The JA4 algorithm is licensed under the BSD 3-Clause license and also free to use - see: FoxIO-LLC/ja4


Contribute

If you have:

Please read the JA4 TLS details!

Testing

Example:

FINGERPRINT
t13d1713h2_5b57614c22b0_748f4c70de1c

APP FROM DB
Mozilla/5.0_(Android_14;_Mobile;_rv:126.0)_Gecko/126.0_Firefox/126.0

DEBUG
raw fingerprint: t_13_d_17_13_h2_002f,0035,009c,009d,1301,1302,1303,c009,c00a,c013,c014,c02b,c02c,c02f,c030,cca8,cca9_0005,000a,000b,000d,0017,001c,0022,002b,0033,fe0d,ff01_0403,0503,0603,0804,0805,0806,0401,0501,0601,0203,0201 

Docker

If you prefer to use Docker, the manual steps can be skipped. Run the docker container from the project root and access https://localhost:6969

docker compose -f test/docker-compose.yaml up --build --watch

--watch will automatically rebuild the container on changes

Local

WARNING: You need to run a version of HAProxy >=3.1 or master

  • Run: bash test/run.sh

  • Access the test website: https://localhost:6969/

  • Or query the API: curl -v https://localhost:6969/api

    {
      "fingerprint": "t13d1517h2_8daaf6152771_b6f405a00624",
      "details": "t_13_d_15_17_h2_002f,0035,009c,009d,1301,1302,1303,c013,c014,c02b,c02c,c02f,c030,cca8,cca9_0005,000a,000b,000d,0012,0017,001b,0023,0029,002b,002d,0033,44cd,fe0d,ff01_0403,0804,0401,0503,0805,0501,0806,0601",
      "app": "Chrome 136"
    }
    

Exit with CTRL+C