htmx 4.0.0 is now available and the important change for teams using htmx 2 is not learning another library, but reviewing attribute inheritance, events, HTTP errors, extensions, and the internal transition from XMLHttpRequest to fetch().
The version was released on August 28, 2026. On GitHub it appears as v4.0.0, with the release published “this 28 Aug 13:00”, and the official announcement explains that htmx 4 arrives after eight months of work.
It also arrived with immediate traction among developers. The Hacker News discussion about “Htmx 4.0” was on the front page on August 28 and, when reviewing the history during this note on August 29, 2026, it showed hundreds of points and more than a hundred comments. That signal doesn’t make a release good by itself, but it does confirm that the topic matters to the community that uses low-level web tools.
The technical point is more concrete: htmx 4 maintains the central idea of htmx, but changes several decisions that affect existing applications.
If you already use htmx in production, this is not a piece of news to read as “a new version came out”. It’s a migration checklist.
What is htmx 4?
htmx 4 is the new major version of htmx, a dependency-free JavaScript library that lets you use HTML attributes to make requests, swaps, transitions, WebSockets, and Server-Sent Events without turning your entire application into a SPA.
The promise remains the same: let the server continue producing HTML and have the browser update parts of the page with attributes like hx-get, hx-post, hx-target, or hx-swap.
What changes in htmx 4 is the internal foundation and several rules around that model.
The team moved internal requests from XMLHttpRequest to the native fetch() API. According to the “What’s New in htmx 4” documentation, all requests use fetch() and that change cannot be reverted. The announcement says that for most users it should be transparent, but it also explains that this migration opened space to rethink extensions, streaming HTML, and asynchronous behavior.
That is the tension of the release.
For a simple application, htmx 4 can feel almost the same as htmx 2. For an application with inherited attributes, JavaScript listeners, special error handling, custom extensions, or header dependencies, there is work to do.
How to install htmx 4?
You can install htmx 4 by pinning the version 4.0.0 in your package manager or loading it from a CDN with a versioned URL.
The official announcement shows this CDN example:
<script src="https://unpkg.com/htmx.org@4.0.0/dist/htmx.min.js"></script>
It also says that htmx 4.0 can be installed via a package manager pointing to the 4.0.0 version.
There’s an important warning: htmx 4.0.0 is not marked as latest on npm at the time of publishing this note. The team explains that it doesn’t want to force accidental updates to users who depend on CDN URLs without a fixed version. That’s why the 2.x line will remain as latest and 4.0 will be marked as next until sometime in 2027.
That changes the practical recommendation.
Don’t use a generic snippet or a URL without a version if you’re testing the migration. Pin 4.0.0, review the guide at four.htmx.org, and don’t blindly trust old indexed pages: during this review, htmx.org/docs/ still showed 2.x installation examples in some sections, while the new htmx 4 documentation lives at four.htmx.org.
For production, moreover, it’s worth sticking to the usual practice: download and serve the file yourself if your policy doesn’t allow depending on public CDNs.
How do I migrate from htmx 2 to htmx 4?
To migrate from htmx 2 to htmx 4, start by running the upgrade-check, reviewing attribute inheritance, and deciding if you need a temporary compatibility layer.
The official announcement shows this command:
npx htmx.org@4.0.0 upgrade-check -- ./templates
The migration guide also documents the pattern with the next channel:
npx htmx.org@next upgrade-check -- ./path/to/project/root
And it allows adding file extensions:
npx htmx.org@next upgrade-check --ext .vue ./path/to/project/root
The tool scans templates and JavaScript files looking for typical htmx 2 code signals: removed attributes, old event names, inheritance patterns, extension changes, and removed APIs. By default, the guide lists support for .html, .php, .js, .ts, .jinja, .jinja2, .j2, .erb, and .hbs. It also notes that the checker requires Python 3.
If you need to reduce risk while migrating, the htmx 4 guide documents two lines of configuration to recover two behaviors from htmx 2:
<script>
htmx.config.implicitInheritance = true;
htmx.config.noSwap = [204, 304, '4xx', '5xx'];
</script>
implicitInheritance re-enables implicit attribute inheritance. noSwap prevents 4xx and 5xx responses from being swapped into the DOM as normal content.
There’s also an htmx-2-compat extension for compatibility, but I’d treat that option as a bridge, not a destination. If you’re going to adopt a major version, the reasonable thing is to let the checker tell you what needs to change and move the code toward the new rules.
What changes with attribute inheritance in htmx 4?
The biggest migration change is that htmx 4 stops inheriting attributes implicitly and requires marking inheritance with the :inherited suffix.
In htmx 2 it was common to put an attribute on a container and expect it to affect internal elements. For example, an hx-confirm on a parent could cover child buttons. In htmx 4, that intention must be explicit:
<!-- htmx 2 -->
<div hx-confirm="Are you sure?">
<button hx-delete="/item/1">Delete</button>
</div>
<!-- htmx 4 -->
<div hx-confirm:inherited="Are you sure?">
<button hx-delete="/item/1">Delete</button>
</div>```
This applies to attributes like `hx-boost`, `hx-target`, `hx-confirm` and other attributes that could previously be inherited.
The change seems small, but it can break important workflows. If your application relies on `hx-headers` for CSRF, on `hx-target` in wrappers, on confirmations placed at the section level, or on inherited patterns in layouts, migration shouldn't be done carelessly.
The good news is that the new behavior is more readable. The bad news is that it forces you to find places where the intention was implicit.
That's why `upgrade-check` isn't an accessory. It's the first serious step of the migration.
## What About HTTP Errors in htmx 4?
htmx 4 swaps into the DOM all HTTP responses except `204` and `304`, so `4xx` and `5xx` responses can now replace content if the server returns HTML.
In htmx 2, `400` and `500` responses weren't swapped by default. In htmx 4, if your server returns a `422` response with validation HTML, that HTML can enter the target. The same can happen with a `500` response if the backend returns a page or fragment that fits the flow.
This can be an improvement if your application already thinks about errors as swappable HTML.
It can also be a surprise if your backend returns full error pages, internal traces in misconfigured environments, or fragments that weren't designed to go into a component.
The htmx 4 guide points to `hx-status` and `noSwap` to control this behavior by status code. The practical decision is simple: review how your forms, validations, session expirations, permission errors, and server errors respond before turning on 4.0 in production.
Migration isn't just about getting the client to work. It's about keeping the HTML contract between server and browser intentional.
## What Changes with Events and JavaScript in htmx 4?
htmx 4 standardizes event names and removes several events tied to `XMLHttpRequest`, so JavaScript listeners are a risky zone in the migration.
The announcement shows changes like these:
htmx:beforeRequest → htmx:before:request
htmx:afterRequest → htmx:after:request
htmx:beforeSwap → htmx:before:swap
htmx:afterSwap → htmx:after:swap
htmx:configRequest → htmx:config:request
The documentation explains that events now follow the `htmx:phase:action[:sub-action]` pattern. It also notes that most error events are consolidated into `htmx:error`, that HTTP errors trigger `htmx:response:error`, that `htmx:xhr:*` events disappear because htmx 4 uses `fetch()`, and that htmx validation events are removed in favor of native browser validation.
Also, some JavaScript APIs are removed or replaced by native browser APIs. For example, the guide recommends using `element.classList.add()` instead of `htmx.addClass()`, `element.remove()` instead of `htmx.remove()`, and `removeEventListener()` instead of `htmx.off()`.
This is the kind of change that doesn't show up in a happy demo.
If your htmx lives mainly in HTML, the impact can be low. If your team integrated htmx with Alpine.js, Stimulus, custom code, analytics, observability, validations, or lifecycle events, review listeners and helpers carefully.
## What About WebSockets, SSE, and Extensions in htmx 4?
htmx 4 makes the extension system more important: WebSockets, SSE, multipart streaming, preload, downloads, Alpine compatibility, and history cache appear as a central part of the new line.
The announcement highlights extensions like:
* `hx-preload` for preloading content.
* `hx-download` for native downloads based on `fetch()`.
* `hx-alpine-compat` to smooth compatibility between htmx and Alpine.js.
* `hx-history-cache` to cache history in `sessionStorage`.
* `hx-sse` for streaming over `text/event-stream`.
* `hx-ws` for sending and receiving over WebSockets.
* `hx-multipart` for streaming over `multipart/mixed`.
* `hx-live` as a small scripting/reactivity solution built into htmx.
Also appearing is `htmax.js`, a bundle that packages htmx along with popular extensions so you don't have to pick each piece separately.
But there's a model shift here: the "What's New" documentation says that extensions are now included directly with scripts and no longer need `hx-ext` to load. If you want to restrict which extensions can register, the guide shows a meta configuration:
```
For teams with extensionsown, the change runs deeper. The extension migration guide says that htmx 4 replaces the callback-based API with event-based hooks. The minimal migration starts by renaming htmx.defineExtension() to htmx.registerExtension(), but a real extension will likely need to map old callbacks to new hooks.
If your project only consumes official extensions, check installation and attributes. If you maintain internal extensions, budget real migration time.
What changes with history in htmx 4?
htmx 4 stops using localStorage as a history cache by default and re-requests the page when navigating back.
The announcement explains why: the snapshot saved in localStorage could include mutations made by third-party JavaScript libraries. When restoring the page, those mutations stayed in the DOM, but the JavaScript logic behind them didn’t necessarily return to the same state.
In htmx 4, when going back in history, htmx re-requests the page and swaps it into <body> or into the [hx-history-elt] element if it exists.
This should reduce a class of awkward bugs in applications that mix server HTML with client scripting. The cost is that history depends more clearly on server behavior, HTTP caches, and the ability to recompose the page.
If you want local cache, the team now points to the hx-history-cache extension, which uses sessionStorage and is designed to coexist better with solutions like Alpine.js.
For teams, the migration question is straightforward: did your application expect instant restoration from localStorage, or can it re-request the page without breaking state, permissions, scroll, and components?
Does htmx 4 immediately replace htmx 2?
htmx 4 doesn’t immediately replace htmx 2 for all projects, and the team itself is avoiding an accidental jump by not marking 4.0 as latest on npm.
The announcement says htmx 2 will continue to be supported indefinitely and there’s no pressure to upgrade. That phrase matters.
A major version freshly released shouldn’t enter production just because it exists. For new projects, htmx 4 is the natural path if you want to start on the current line. For existing projects on htmx 2, the question isn’t “should I migrate today?”, but “how explicit are my contracts?”.
Check especially:
- Legacy attributes in layouts and components.
- Handling of
4xxand5xxresponses. - htmx event listeners in JavaScript.
- Use of removed JavaScript APIs.
- Dependencies on
localStoragefor history. - Official or custom extensions.
- Headers your backend or server libraries use.
That list is the value of the release for yoDEV: not an abstract celebration of “less JavaScript”, but a guide for knowing where to look before breaking an app that already works.
Why does htmx 4 matter for developers in Iberoamerica?
htmx 4 matters because it shows that the server-side web stack isn’t frozen: it keeps gaining modern tools without completely surrendering to the SPA model.
For years, many teams felt the only serious way to build modern web interfaces was to move more state, more routing, more validation, and more rendering to the client. htmx pushed an alternative: use HTML as the medium of application, keep the server close to the product, and add interactivity where it counts.
htmx 4 doesn’t abandon that thesis. It updates it.
The move to fetch() aligns the internals with the modern browser. Explicit inheritance makes contracts more readable. Standardized events make integrating observability and scripting more reasonable. Streaming extensions push cases where HTML can travel incrementally. hx-partial, morph swaps, and htmax.js expand the toolkit without turning htmx into a monolithic framework.
The signal for teams isn’t that they should replace React, Vue, Svelte, or any other stack. That discussion usually becomes religious too quickly.
The useful signal is different: if your product already expresses itself well as server HTML, htmx 4 gives you a modern path to stay there with less ceremony. And if your team maintains an htmx 2 application, this release forces you to take inventory of the implicit parts of the system.
That’s healthy.
The best migrations aren’t the ones that change everything. They’re the ones that uncover what assumptions were hidden.
htmx 4 brings exactly that kind of work: small in appearance, very concrete in impact.