Forza Horizon DualSense Adaptive Triggers: a Python bridge for PC trigger feedback
Forza Horizon DualSense Adaptive Triggers
At a glance
- What is it?
- This Python app reads Forza Horizon telemetry on UDP port 5300 and writes only the adaptive trigger bytes of a DualSense controller, leaving Steam Input's rumble and button mapping untouched.
- Who is it for?
- Adopt it if you play Forza Horizon on PC with a DualSense and want brake and throttle resistance that Steam Input does not provide; the launcher scripts and the 324-byte telemetry path are the whole story. Skip it if you use a different pad, if you play through a store version without a controller redirector such as SISR, or if you want the rumble motors driven by telemetry, which this app deliberately does not touch.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 125 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Star history
- HamzaYslmn/Forza-Horizon-DualSense-Python460 ★ · +7
| Repository | 2026-09-21 | 2026-10-23 |
|---|---|---|
| HamzaYslmn/Forza-Horizon-DualSense-Python | 453 | 460 |
7 Stars in the last 32 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
The gap this fills between Forza telemetry and Steam Input
Forza Horizon already broadcasts car state over UDP, and Steam Input already drives the DualSense rumble motors and button mapping. Neither of them touches the adaptive trigger actuators. That is the specific hole this project targets: the README states plainly that "Steam Input doesn't use the DualSense's adaptive triggers," and this app exists to write those bits. The audience is narrow and well defined: PC players who own a DualSense, run Forza Horizon through Steam, and want the left trigger to stiffen as a brake and the right trigger to resist as a throttle. If you play with an Xbox pad, a wheel, or a keyboard, nothing here applies to you. The README also thanks a sponsor for gifting Forza Horizon 6, which tells you the author is testing against a recent title in the series rather than only the older one.
How the telemetry path and HID writes avoid fighting Steam
The data flow is documented as a single chain. Forza Horizon sends 324-byte telemetry packets to UDP port 5300. The app parses them and issues HID writes that contain trigger data only. In parallel, Steam Input issues its own HID writes for rumble and buttons. The README's diagram makes the split explicit: Steam owns the rumble motors and button mapping, while this app flips only the adaptive trigger bits, named as valid_flag0 bits 0x04 and 0x08. The second design decision is that the HID device is opened in non-blocking mode, so writes fire immediately rather than waiting on the controller. Nothing queues, and Steam is not stalled. That is the mechanism behind the claim that both can run at once without breaking each other. What the README does not describe is how it recovers if the controller disconnects mid-session; the SISR section tells you to close SISR, restart the app, then reopen SISR, which suggests restarting the app is the recovery path rather than a reconnect loop inside it.
Installing on Windows with win_start.bat and uv
The recommended install is a launcher script, not a package. Download win_start.bat from the latest release, put it in an empty folder, and double-click it. The script downloads the app, prepares the environment, runs it, and checks for updates on later runs. The README recommends installing uv yourself first so the script does not attempt its own auto-install, which Windows may block.
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"If PowerShell refuses the auto-install with an execution policy error, the README gives this recovery: open a PowerShell window in the folder, run the command below, answer Y, then run the launcher again.
Set-ExecutionPolicy RemoteSigned -scope CurrentUserThere is also a standalone Windows .exe attached to each release, but the README calls it experimental and still recommends win_start.bat because it self-updates and behaves the same across Windows versions. For developers who want to run from source, the README shows the clone, cd into src, uv sync, uv run main.py sequence.
In-game Data Out settings and the first run
Before the app can do anything, the game has to send telemetry somewhere. In Forza Horizon, open Settings, then HUD and Gameplay, and scroll to the bottom. The README specifies Data Out as ON, Data Out IP Address as 127.0.0.1, and Data Out IP Port as 5300. Those match the UDP port in the architecture diagram, so a mismatch here is the first thing to check if nothing happens. The README notes that on some versions of Forza, 127.0.0.1 may not work and suggests trying ::1, the IPv6 loopback, instead. Once telemetry is flowing, start the app and wait for the short pulse on the triggers. That pulse is the confirmation that the HID side is connected. If you use SISR for the Xbox App or Microsoft Store version, the order matters: this app first, then SISR and Steam, then the game. The README warns that Steam can grab the physical DualSense exclusively and block this app if you reverse that order.
Linux needs libhidapi and a udev rule before anything works
The Linux path is not just the shell script. The README lists libhidapi as a dependency, with distro-specific commands, and a udev rule at app/packaging/linux/70-dualsense.rules that has to be installed. After installing the rule, unplug and replug the controller once. The tray icon has its own dependency chain on Wayland, because it needs the appindicator backend that X11 does not require. The README lists build packages per distro so the launcher can build PyGObject into its virtual environment, including build-essential, pkg-config, python3-dev, libcairo2-dev, libgirepository-2.0-dev, libayatana-appindicator3-1 and gir1.2-ayatanaappindicator3-0.1 on Debian and Ubuntu. That is a heavier prerequisite set than the Windows path, and it is the main reason a Linux user should read the install section before downloading anything.
Where it stops: rumble, other controllers, and store versions
The deliberate byte split is also the limitation. The app writes trigger bits and nothing else, so the rumble motors stay under Steam Input's control and are not driven by telemetry. If you expected engine vibration tied to revs, this project will not give it to you. It is also DualSense-specific; the README names no other controller. The Xbox App and Microsoft Store case is the one where the tool is not enough on its own: the README says you need a tool that makes the game see an Xbox controller, and points to SISR as one option. That adds a second moving part and a strict launch order. The README also documents a specific failure mode for that combination: if the controller disconnects while playing, close SISR, restart this app, then open SISR again. Nothing in the README describes a reconnect path that avoids that manual cycle.
How it compares with a general controller remapper
SISR solves a different problem. Its job, as the README describes it, is to redirect Steam Input to the system level and emulate a real Xbox controller so Windows Store apps and anti-cheat-protected games accept the input. It is about making the game see a controller at all. This app assumes the game already sees the controller and adds trigger resistance on top. The two are complementary, which is exactly why the README spends a section on launch order: SISR routes the controller through Steam Input, and Steam can then hold the physical DualSense exclusively. A general remapper will not give you the brake stiffening or the ABS buzz, and this app will not make a Windows Store copy of Forza recognize a DualSense. Choosing between them is not the question; knowing which one you are missing is.
Maintenance, licence and what upgrading costs you
The last push to the default branch was on 2026-06-20, and the most recent release, v1.6.2, is dated 2026-06-13, with v1.6.1 and v1.6.0 both on 2026-05-31. That is a project that has been moving recently, though the README does not describe a release cadence or a support window. Upgrades are cheap by design on Windows: win_start.bat checks for updates on each run, so a user who stays on the recommended path gets new versions without a manual step. The standalone .exe has no such mechanism and the README calls it experimental. On Linux, the launcher builds dependencies into a virtual environment, so a change in the appindicator or hidapi requirements can mean reinstalling system packages rather than just re-running the script. The repository carries a LICENSE file, but the metadata reports the licence as NOASSERTION, meaning no standard licence identifier could be determined from it. Read the LICENSE file itself before you redistribute the app or bundle it with anything; nothing here is legal advice.
Editorial conclusion
Adopt it if you play Forza Horizon on PC with a DualSense and want brake and throttle resistance that Steam Input does not provide; the launcher scripts and the 324-byte telemetry path are the whole story. Skip it if you use a different pad, if you play through a store version without a controller redirector such as SISR, or if you want the rumble motors driven by telemetry, which this app deliberately does not touch. Before you rely on it, verify three things: that Data Out is on with IP 127.0.0.1 and port 5300, that the app pulses the triggers at startup before you launch Steam or SISR, and that the Linux udev rule is installed if the HID device is not found.
Frequently asked questions
Does Forza Horizon DualSense Python give Forza Horizon 6 DualSense support on PC?
It adds adaptive trigger feedback, not full DualSense support. The README states that Steam Input already handles rumble and button mapping and that this app only writes the adaptive trigger bits for the brake and throttle.
Can I play Forza Horizon 5 with a controller while running this app?
Yes. The app reads telemetry over UDP and writes only trigger bytes, while Steam Input keeps writing rumble and buttons, so the README says both can run at the same time without breaking each other.
Why is Forza Horizon DualSense Python not receiving telemetry from the game?
Check the in-game Data Out settings first: Data Out ON, IP address 127.0.0.1, port 5300. The README notes that on some versions of Forza 127.0.0.1 may not work and suggests entering ::1 instead.
My controller is not vibrating in Forza Horizon 6. Does this app fix that?
No. The app deliberately writes only the adaptive trigger bits (valid_flag0 bits 0x04 and 0x08), and the README assigns the rumble motors to Steam Input.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/hamzayslmn-forza-horizon-dualsense-python)Star history chart for your README
[](https://hysenlabs.com/projects/hamzayslmn-forza-horizon-dualsense-python)Was this useful?