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.luato 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.luain theglobalsection - 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:
- Found an issue/bug - please report it
- Have an idea on how to improve it - feel free to start a discussion
- PRs are welcome
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