Summarizer

Fetch as axios replacement

Arguments that native fetch has been stable since Node 21, making axios unnecessary, though many legacy codebases and LLM-generated code still use it

← Back to Axios compromised on NPM – Malicious versions drop remote access trojan

While Node’s native `fetch` is now stable and theoretically makes Axios obsolete, many developers argue that the native API remains too "bare-bones," lacking essential built-in features like interceptors, automatic JSON handling, and robust upload progress tracking. This functional gap often forces teams to choose between the convenience of a mature library and the security of writing custom, "homegrown" wrappers that some view as an unnecessary reinvention of the wheel. Transitioning is further complicated by the library's deep entrenchment in legacy systems, transitive dependencies, and the training data of AI models that continue to propagate its usage. Ultimately, the debate centers on whether the "batteries-included" convenience of Axios justifies its use as a third-party dependency in an era where minimizing supply-chain attack surfaces is becoming a critical security priority.

75 comments tagged with this topic

View on HN · Topics
depends, JavaScript in the Browser has many useful things available, which I miss with python, e.g., fetch, which in Python you need a separate package like requests to avoid a clunky API. Java had this issue for long time as well, since Java 11 there is the HttpClient with a convenient API.
View on HN · Topics
Irony is that Node has no need for Axios, native fetch support has been there for years, so in terms of network requests it is batteries included.
View on HN · Topics
It doesn't matter. We pulled axios out of our codebase, but it still ends up in there as a child or peer from 40 other dependencies. Many from major vendors like datadog, slack, twilio, nx (in the gcs-cache extension), etc...
View on HN · Topics
Yep, got stung because a bunch of things still pull in axios even though we don't use it.
View on HN · Topics
People use axios or ky because with fetch you inevitably end up writing a small wrapper on top of it anyway.
View on HN · Topics
Fetch has also lacked support for features that xhr has had for over a decade now. For example upload progress. It's slowly catching up though, upload progress is the only thing I'd choose xhr for.
View on HN · Topics
You can pipe through a TransformStream that counts how many bytes you've uploaded, right?
View on HN · Topics
That would show how quickly the data is passing into the native fetch call but doesn’t account for kind of internal buffer it might have, network latency etc
View on HN · Topics
That is a way to approximate it, though I'd be curious to know the semantics compared to xhr - would they both show the same value at the same network lifecycle of a given byte?
View on HN · Topics
Some might say the tradeoff of writing a small wrapper is worth it given what’s been demonstrated here.
View on HN · Topics
In my experience people feel the need to wrap axios too.
View on HN · Topics
AI was trained on Axios wrappers, so it's just going to be wrappers all the way down. Look inside any company "API Client" and it's just a branded wrapper around Axios.
View on HN · Topics
Speak for yourself, Claude works fine with fetch on my system.
View on HN · Topics
Node fetch is relatively new. Wasn't marked stable until 2023, though I've used it since like 2018.
View on HN · Topics
I'm not sure fetch is a good server-side API. The typical fetch-based code snippet `fetch(API_URL).then(r => r.json())` has no response body size limit and can potentially bring down a server due to memory exhaustion if the endpoint at API_URL malfunctions for some reason. Fine in the browser but to me it should be a no-no on the server.
View on HN · Topics
> I'm not sure fetch is a good server-side API. The typical fetch-based code snippet `fetch(API_URL).then(r => r.json())` has no response body size limit and can potentially bring down a server due to memory exhaustion if the endpoint at API_URL malfunctions for some reason. Fine in the browser but to me it should be a no-no on the server. Nor is fetch a good client-side API either; you want progress indicators, on both upload and download. Fetch is a poor API all-round.
View on HN · Topics
Hm, I don't think axios would do much better here. `fetch` is the official replacement for axios. If both are flawed that's another topic
View on HN · Topics
Axios has maxContentLength and maxBodyLength options. I would probably go with undici nowadays though (it also has maxResponseSize).
View on HN · Topics
> `fetch` is the official replacement for axios. No. Axios is still maintained. They have not deprecated the project in favor of fetch.
View on HN · Topics
I'm not saying that axios is unmaintained, I'm saying that if you want something like axios from the standard lib, fetch is the closest thing you get to official
View on HN · Topics
Sure but Axios determine what the official replacement for Axios is.
View on HN · Topics
It's not deprecated, it's obsoleted.
View on HN · Topics
It doesn't have a need _now_. Axios is more than 10 years old now, and even before axios other libraries did the same utility of making requests easier
View on HN · Topics
Browsers too. It’s not needed anymore.
View on HN · Topics
I work in a NIS2 compliance sector, and we basically use Go and Python for everything. Go is awesome, Python isn't as such. Go didn't always come with the awesome stllib that it does today, which is likely partly why a lot of people still use things like Gin for web frameworks rather than simply using the standard library. Having worked with a lot of web frameworks, the one Go comes with is nice and easy enough to extend. Python is terrible, but on the plus side it's relatively easy to write your own libraries with Python, and use C/Zig to do so if you need it. The biggest challenges for us is that we aren't going to write a better MSSQL driver than Microsoft, so we use quite a bit of dependencies from them since we are married with Azure. These live in a little more isolation than what you might expect, so they aren't updated quite as often as many places might. Still, it's a relatively low risk factor that we can accept. Our React projects are the contrast. They live in total and complete isolation, both in development and in production. You're not going to work on React on a computer that will be connected to any sort of internal resources. We've also had to write a novel's worth of legal bullshit explaining how we can't realistically review every line of code from React dependencies for compliance. Anyway, I don't think JS/TS is that bad. It has a lot of issues, but then, you could always have written your own wrapper ontop of Node's fetch instead of using Axios. Which I guess is where working in the NIS2 compliance sector makes things a little bit different, because we'd always chose to write the wrapper instead of using one others made. With the few exceptions for Microsoft products that I mentioned earlier.
View on HN · Topics
> "Batteries included" ecosystems are the only persistent solution to the package manager problem. The irony in this case is that axios is not really needed now given that fetch is part of the JS std lib.
View on HN · Topics
But javascript is batteries included in this case, you can use xmlhttprequest or fetch
View on HN · Topics
I can't even imagine the scale of the impact with Axios being compromised, nearly every other project uses it for some reason instead of fetch (I never understood why). Also from the report: > Neither malicious version contains a single line of malicious code inside axios itself. Instead, both inject a fake dependency, [email protected] , a package that is never imported anywhere in the axios source, whose only purpose is to run a postinstall script that deploys a cross-platform remote access trojan (RAT) Good news for pnpm/bun users who have to manually approve postinstall scripts.
View on HN · Topics
> nearly every other project uses it for some reason instead of fetch (I never understood why). Fetch wasn't added to Node.js as a core package until version 18, and wasn't considered stable until version 21. Axios has been around much longer and was made part of popular frameworks and tutorials, which helps continue to propagate it's usage.
View on HN · Topics
Also it has interceptors, which allow you to build easily reusable pieces of code - loggers, oauth, retriers, execution time trackers etc. These are so much better than the interface fetch offers you, unfortunately.
View on HN · Topics
You can do all of that in fetch really easily with the init object. fetch('https://api.example.com/data', { headers: { 'Authorization': 'Bearer ' + accessToken } })
View on HN · Topics
There are pretty much two usage patterns that come up all the time: 1- automatically add bearer tokens to requests rather than manually specifying them every single time 2- automatically dispatch some event or function when a 401 response is returned to clear the stale user session and return them to a login page. There's no reason to repeat this logic in every single place you make an API call. Likewise, every response I get is JSON. There's no reason to manually unwrap the response into JSON every time. Finally, there's some nice mocking utilities for axios for unit testing different responses and error codes. You're either going to copy/paste code everywhere, or you will write your own helper functions and never touch fetch directly. Axios... just works. No need to reinvent anything, and there's a ton of other handy features the GP mentioned as well you may or may not find yourself needing.
View on HN · Topics
Interceptors are just wrappers in disguise. const myfetch = async (req, options) => { let options = options || {}; options.headers = options.headers || {}; options.headers['Authorization'] = token; let res = await fetch(new Request(req, options)); if (res.status == 401) { // do your thing throw new Error("oh no"); } return res; } Convenience is a thing, but it doesn't require a massive library.
View on HN · Topics
That fetch requires so many users to rewrite the same code - that was already handled well by every existing node HTTP client- says something about the standards process.
View on HN · Topics
It could also be trivially written for XMLHttpRequest or any node client if needed. Would be nice if they had always been the same, but oh well - having a server and client version isn't that bad. Because it is so few lines it is much more sensible to have everyone duplicate that little snippet manually than import a library and write interceptors for that ... (Not only because the integration with the library would likely be more lines of code, but also because a library is a significantly liability on several levels that must be justified by significant , not minor, recurring savings.)
View on HN · Topics
> Because it is so few lines it is much more sensible to have everyone duplicate that little snippet manually Mine's about 100 LOC. There's a lot you can get wrong. Having a way to use a known working version and update that rather than adding a hundred potentially unnecessary lines of code is a good thing. https://github.com/mikemaccana/fetch-unfucked/blob/master/sr... > import a library and write interceptors for that... What you suggesting people would have to intercept? Just import a library you trust and use it.
View on HN · Topics
Your wrapper does do a bunch of extra things that aren't necessary, but pulling in a library here is a far greater maintenance and security liability than writing those 100 lines of trivial code for the umpteenth time. So yes you should just write and keep those lines. The fact that you haven't touched that file in 3 years is a great anecdotal indicator of how little maintenance such a wrapper requires, and so the primary reason for using a library is non-existent. Not like the fetch API changes in any notable way, nor does the needs of the app making API calls, and as long as the wrapper is slim it won't get in the way of an app changing its demands of fetch. Now, if we were dealing with constantly changing lines, several hundred or even thousand lines, etc., then it would be a different story.
View on HN · Topics
But you said so yourself they are necessary… otherwise you would just use fetch. This reasoning is going around in circles.
View on HN · Topics
> Likewise, every response I get is JSON. fetch responses have a .json() method. It's literally the first example in MDN: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/U... It's literally easier than not using JSON because I have to think about if I want `repsponse.text()` or `response.body()`.
View on HN · Topics
that's such a weak argument. you can write about 20 lines of code to do exactly this without requiring a third party library.
View on HN · Topics
> usage patterns IMO interceptors are bad. they hide what might get transformed with the API call at the place it is being used. > Likewise, every response I get is JSON. There's no reason to manually unwrap the response into JSON every time. This is not true unless you are not interfacing with your own backends. even then why not just make a helper that unwraps as json by default but can be passed an arg to parse as something else
View on HN · Topics
One more use case for Axios is it automatically follows redirects, forwarding headers, and more importantly, omiting or rewriting the headers that shouldn't be forwarded for security reasons.
View on HN · Topics
fetch automatically follows redirects, fetch will forward your headers, omitting or rewriting headers is how security breaks… now a scraper got through because it’s masquerading as Chrome.
View on HN · Topics
What does an interceptor in the RequestInit look like?
View on HN · Topics
A wrapper function around fetch… that’s what interceptors are…
View on HN · Topics
It also supports proxies which is important to some corporate back-end scenarios
View on HN · Topics
fetch supports proxies
View on HN · Topics
Before that we had node-fetch. If you already use a dependency why not one that's pretty much what will come natively to every JS runtime soon.
View on HN · Topics
The fetch API is designed for browsers. It's not designed for servers. Fetch may work for a particular use case on the server, it may not. Servers have needs over and above what a browser allows the client to do.
View on HN · Topics
Now I'm curious, because we have a big server side code base using fetch(). What are you using that doesn't work with fetch? Especially since axios nowadays has a fetch adapter.
View on HN · Topics
Right. Though I would've used the built in xhr then. Not going to install a dep just to make http calls.
View on HN · Topics
> I can't even imagine the scale of the impact with Axios being compromised, nearly every other project uses it for some reason instead of fetch (I never understood why). You can remember this answer for every time you ask same question again: "Coz whatever else/builtin was before was annoying enough for common use cases"
View on HN · Topics
> (I never understood why). I spent two years trying to get it out of a project that began long after Axios had become redundant but it's very hard to go back and challenge decisions like this because every business priority is aligned against this kind of work. I expect libraries built on top of fetch will be the next to be compromised, because why would you use fetch without an arbitrary layer of syntactic sugar...
View on HN · Topics
There was never the business value. But now remember this axios case and use it as ammo for the next issue. Just don’t abuse it
View on HN · Topics
>(I never understood why). Because axios existed before the builtin fetch, and so there's a lot of stackoverflow answers explaining how to use fetch, and the llm models are trained on that, so they will write axios requests instead of fetch
View on HN · Topics
The postinstall script vector is getting all the attention, but IMO the scarier part is how the attacker chain works: compromise one package's credentials, use that access to pivot to the next target. Trivy -> LiteLLM -> now potentially axios. Each compromised package becomes a credential harvester for the next round.\n\nThe min-release-age configs (now in npm, pnpm, bun, uv) are a good start, but they only work as herd immunity — you need enough early adopters installing fresh releases to trigger detection before the 7-day window expires for everyone else. It's basically a bet that security researchers will catch it faster than your cooldown period.\n\nFor Node specifically: if you're still using axios for new projects, it's worth asking why. Native fetch has been stable in Node since v21. One less dependency in your tree is one less attack surface.
View on HN · Topics
It's more to do with the standard library being so barren of common application needs, and looking for a solution that the community has gotten behind. Axios has been a common dependency in many codebases, because it is a solid solution that many have already used. Every developer could try building all the libraries that they would reach for themselves, but then each company has now taken on the task of ensuring their own (much larger) codebase is free from security issues, on top of taking care of their own issues and bugs.
View on HN · Topics
Most of axios' functionality has effectively been promoted to a language feature as `fetch`, but the problem is people don't bother to migrate. I've migrated our direct usage of it but it's still pulled in transitively in several parts of our codebase. Even left-pad is still getting 1.6 million weekly downloads.
View on HN · Topics
Annoyingly, the times I reach for axios and similar is when I need to keep track of upload progress, which I could only do with XMLHttpRequest, not fetch, unless I've missed some recent browser changes, and the API of XMLHttpRequest remains as poor as the first times I had to use it. Download progress been supported by fetch since you can track chunks yourself, but somehow they didn't think to do that for requests for some reason, only responses.
View on HN · Topics
>maybe the community could chip in to buy the authors a couple of YubiHSM There's no community, the users of axios are devs that looked at stackoverflow for "how to download a file in javascript", they barely know or care what axios is. Now the users of axios are devs that ask Claude Code or Codex to scrape a website or make a dashboard, they don't even know about the word axios. I personally had to delete axios a couple of time from my codebase when working with junior devs.
View on HN · Topics
Even better would be to not use so many libs. Most use cases will do fine with native `fetch`.
View on HN · Topics
The amount of people still using this instead of fetch. Nonetheless when wasn't axios, it would be something else. This is why corporations doing it right don't allow installing the Internet into dev machines. Yet everyone gets to throw their joke about PC virus, while having learnt nothing from it.
View on HN · Topics
> The amount of people still using this instead of fetch. People are lazy. And sometimes they find old stuff via a google search and use that.
View on HN · Topics
My main question here is mostly why so many people still rely on axios for their fetch implementation. Native fetch has been a thing in the JavaScript world for so long, and the DX gains to using axios over it are miniscule. The only thing I can think of is axios instances, but you can easily write a tiny wrapper for fetch that would do the same. This is a genuine question - if you still use axios, why exactly?
View on HN · Topics
One more reason to use Fetch
View on HN · Topics
Stop trying to make Fetch happen.
View on HN · Topics
No, I will not stop trying to create a more standardized and secure software ecosystem.
View on HN · Topics
is there even a reason to use axios?
View on HN · Topics
until Node is compromised
View on HN · Topics
I used axios in the distant past but haven't used it whenever I had my say in the past five years. You don't need it, and for special things like retries I could roll my own just fine. Now ai will roll it for you
View on HN · Topics
1/5 of your CLI and 1/3 of your gui apps are npm based. Each one has 400+ dependencies , none notable enough to go viral when they are breached. And who knows what other packages are currently compromised. We all have 30+ node_modules on our disks, and 2/3 of them were shipped by outside vendors , packaged in an archive. “I’m smart I use fetch instead of axios”. “I pin my versions” – sure but certainly one of your npx or Electron apps uses axios or another less notably compromised package. Let’s
View on HN · Topics
Glad to be using native fetch.
View on HN · Topics
node:fetch is all you need, simple and effective
View on HN · Topics
I've been saying for ages, use xmlhttprequest, or hell, even fetch(). Stop downloading code from the internet unless it's a major strategic decision.
View on HN · Topics
Well, this particular case could be wholly avoided if it didn't take 2 decades to get competent HTTP(S) client into core language