Thank you so much for writing DataStar. It has been life-changing in reducing JavaScript client-side issues. Here is a fix for something I stumbled upon as I was migrating away from HTMX.
The remainder of this post is written by Claude Code.
fetch() refuses to use a URL that contains credentials (https://user:pass@host/…). Because Datastar's @get/@post are built on fetch(), opening a page with credentials in the URL — e.g. behind HTTP Basic Auth — makes every Datastar request fail. HTMX never hit this because it uses XMLHttpRequest, which tolerates credentialed URLs. The small script below restores parity, so Datastar "just works" behind Basic Auth.
When the page URL carries credentials, two browser behaviors break Datastar:
new Request(url)throws beforefetch()is ever called:TypeError: Failed to construct 'Request': Request cannot be constructed from a URL that includes credentials.- Even past that,
fetch()itself rejects the credentialed URL.
The Fetch standard disallows credentials in the request URL. XMLHttpRequest (HTMX's transport) does not — which is why the same app worked under HTMX and stops working under Datastar.
The browser constructs the Request object before calling fetch(input, init). So a wrapper around window.fetch never even runs — the TypeError is thrown at Request construction. You have to patch the Request constructor too.
datastar-auth-fix.js (in this gist) patches both window.Request (via a Proxy, so instanceof and the prototype chain stay intact) and window.fetch, stripping the credentials from the URL before the native code sees them. It is a no-op unless the page URL actually contains user:pass@, and the browser keeps sending the cached Authorization header after the first auth challenge — so requests stay authenticated.
Load it before the Datastar module:
<script src="/js/datastar-auth-fix.js"></script>
<script type="module" src="/datastar.js"></script>Maybe worth considering: stripping credentials from the URL inside Datastar's own fetch path (before constructing the Request) would make @get/@post work behind Basic Auth out of the box, matching HTMX. The credentials can't travel in a fetch URL anyway, and the browser attaches the Authorization header automatically. Sharing the standalone fix here in case it's useful to others.
Wouldn't it be possible to send the credentials in the
Authorizationheader directly instead of in the URL? Then no need to patch anything, right? Eg@get('url', {headers: {Authorization: 'Basic ...'}})EDIT: htmx 4 is built on Fetch API, so it would have the same issue if you had tried to upgrade.