Axios to biblioteka JavaScript do wysyłania zapytań HTTP w przeglądarce i w Node.js, oparta na obietnicach (Promise). Powstała w 2014 roku, zanim istniał fetch, więc nie chodziło o zgodność z przeglądarkami, tylko o wygodne API ponad XMLHttpRequest. Dziś fetch jest wbudowany w każdą przeglądarkę i Node.js, więc do prostych zapytań wystarczy, a axios warto dodać, gdy potrzebujesz interceptorów, automatycznego odrzucania błędów HTTP i gotowego timeoutu.
Jeśli zaglądasz do kodu aplikacji frontendowej, bardzo często zobaczysz axios.get(...). Zaraz obok bywa zwykły fetch. To rodzi naturalne pytanie: czy to dwa sposoby na to samo i czy wciąż potrzebujesz zewnętrznej biblioteki, skoro przeglądarka ma własne narzędzie? Sprawdziłem to na działającym kodzie i poniżej pokazuję, co naprawdę się różni.
Czym jest axios?
Axios to biblioteka do komunikacji z serwerem przez HTTP. Wysyłasz nią zapytania do API (GET, POST, PUT, DELETE), a w odpowiedzi dostajesz obietnicę (Promise) z danymi. Działa w dwóch środowiskach: w przeglądarce i w Node.js, z tym samym zapisem w obu. To ostatnie jest jej cechą od początku, bo pierwsze wydanie opisano jako „Promise based XHR library”, czyli opakowanie na XMLHttpRequest z obietnicami.
Popularność jest ogromna: według API npm w tygodniu 31.10–6.11.2026 pobrano ją ok. 145 mln razy. Dla porównania jQuery miało w tym samym tygodniu ok. 18 mln pobrań, a mniejszy odpowiednik ky około 10 mln. Duża część tych pobrań to zależności zagnieżdżone w innych pakietach, więc liczba nie oznacza 145 mln świadomych decyzji, ale pokazuje, że z axios zetkniesz się w pracy niemal na pewno.
Dlaczego powstał axios? Czy z tego samego powodu co jQuery?
Pytanie jest uzasadnione, bo oba projekty łączy jedno: ułatwiały życie, kiedy natywne narzędzia były niewygodne. Ale powód był inny.
| jQuery (2006) | Axios (2014) | |
|---|---|---|
| Główny problem | Różnice w działaniu przeglądarek (DOM, zdarzenia, AJAX) | Niewygodne XMLHttpRequest, brak obietnic |
| Czy chodziło o zgodność z przeglądarkami? | Tak, to była jego główna siła | Tylko pobocznie |
| Co robiło dobrze | Jednolite API na każdej przeglądarce | Obietnice, JSON, ten sam kod w przeglądarce i Node.js |
| Natywna alternatywa | Pojawiła się po latach (querySelector, classList, addEventListener) | fetch (pojawił się w przeglądarkach dopiero po 2014 roku, dziś jest też wbudowany w Node.js) |
W 2014 roku fetch jeszcze nie istniał. Żeby wysłać zapytanie, pisałeś new XMLHttpRequest(), ustawiałeś nasłuchiwanie na zmianę stanu i ręcznie parsowałeś odpowiedź. Axios zamknął to w jednej linijce i oddał wynik jako Promise. Do tego dawał to samo API po stronie serwera w Node.js, co wtedy było sporym ułatwieniem, bo trzeba było używać innego modułu http.
Można więc powiedzieć: jQuery wygrywało zgodnością z przeglądarkami, a axios wygodą pracy z HTTP. Więcej o historii tamtej biblioteki znajdziesz w artykule czym jest jQuery i dlaczego był popularny.
Jak wysłać zapytanie w axios?
Instalacja to npm install axios. Pobranie danych wygląda tak:
import axios from "axios";
const response = await axios.get("https://api.example.com/users/1");
console.log(response.data); // { id: 1, name: "Ala" }
Najważniejsze: dane z odpowiedzi leżą w response.data, już po sparsowaniu z JSON. Wysłanie danych do serwera jest równie krótkie:
const response = await axios.post("https://api.example.com/users", {
name: "Ala",
});
Axios sam zamienia obiekt na JSON i ustawia nagłówek Content-Type: application/json. Sprawdziłem to na lokalnym serwerze: serwer dostał nagłówek application/json i ciało {"a":1} bez żadnej dodatkowej konfiguracji.
Jak to samo zrobić w fetch?
Natywny fetch robi to samo, ale wymaga trochę więcej ręcznej pracy:
const response = await fetch("https://api.example.com/users", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name: "Ala" }),
});
const data = await response.json();
Dwa kroki, których w axios nie ma: sam zamieniasz obiekt na tekst (JSON.stringify) i sam odczytujesz odpowiedź (response.json()). Jeśli chcesz zobaczyć, jak fetch działa od podstaw, zacznij od modułu API i fetch albo od artykułu o lokalnym API z json-serverem.
Czym axios różni się od fetch w praktyce?
To jest sedno porównania. Przetestowałem poniższe różnice w Node.js 22 z axios 1.21.0.
| Sytuacja | fetch | axios |
|---|---|---|
| Odpowiedź 404 lub 500 | Obietnica zostaje spełniona, response.ok === false | Obietnica zostaje odrzucona (AxiosError) |
| Dane z odpowiedzi | await response.json() | response.data |
| Wysyłanie obiektu jako JSON | JSON.stringify + nagłówek | automatycznie |
| Timeout | AbortSignal.timeout(ms) | opcja timeout: ms |
| Wspólna logika dla wszystkich zapytań | własna funkcja opakowująca | interceptory |
| Dodatkowa biblioteka | nie, jest wbudowany | tak, ok. 26 KB po gzip |
Dlaczego fetch nie rzuca błędu przy 404?
To najczęstsza pułapka początkujących. Dla fetch błędem jest tylko brak połączenia z serwerem. Jeśli serwer odpowie kodem 404 albo 500, zapytanie uznane jest za udane, bo „odpowiedź przyszła”. W teście dostałem:
fetch 404 -> resolved, ok = false 404
axios 404 -> rejected: AxiosError ERR_BAD_REQUEST Request failed with status code 404
W praktyce z fetch musisz zawsze sprawdzić response.ok, inaczej blok catch nigdy się nie wykona przy błędach serwera. Axios odrzuca obietnicę dla kodów poza zakresem 2xx, więc błędy trafiają do catch, a ciało odpowiedzi serwera (np. {"message":"Nie ma"}) leży w error.response.data. Jeśli kiedykolwiek kod „działał w fetch, a w axios nie”, zwykle chodzi właśnie o tę różnicę: w jednym przypadku błąd HTTP jest zwykłą odpowiedzią, w drugim wyjątkiem.
Jak ustawić timeout?
W axios: axios.get(url, { timeout: 5000 }). W teście dla 300 ms dostałem błąd z kodem ECONNABORTED i komunikatem „timeout of 300ms exceeded”. W fetch robi się to przez sygnał przerwania:
const response = await fetch(url, { signal: AbortSignal.timeout(5000) });
W teście przerwanie dało TimeoutError. Ta różnica zmalała, odkąd AbortSignal.timeout() jest dostępne w nowoczesnych środowiskach, a wcześniej wymagało to AbortController i setTimeout. Uwaga: ani fetch, ani axios nie mają domyślnego limitu czasu, więc bez jawnego ustawienia zapytanie może wisieć bardzo długo.
Co to są interceptory w axios i do czego służą?
Interceptor to funkcja, która uruchamia się dla każdego zapytania albo każdej odpowiedzi, zanim trafią do twojego kodu. To najmocniejszy argument za axios i jednocześnie temat, o który pytają najczęściej: pytanie o interceptory ma na Stack Overflow ponad 300 tys. wyświetleń.
Typowy przykład: dołączanie tokenu do każdego zapytania.
const api = axios.create({ baseURL: "https://api.example.com" });
api.interceptors.request.use((config) => {
config.headers.Authorization = `Bearer ${getToken()}`;
return config;
});
W teście serwer dostał nagłówek Authorization: Bearer tok w każdym zapytaniu wysłanym przez api. Drugi typowy przypadek to obsługa błędu 401 w jednym miejscu:
api.interceptors.response.use(
(response) => response,
(error) => {
if (error.response?.status === 401) {
logout(); // przekieruj na ekran logowania
}
return Promise.reject(error);
}
);
Dzięki temu nie sprawdzasz statusu 401 w dziesięciu różnych komponentach. Ten sam kod z fetch wymaga własnej funkcji, przez którą przechodzą wszystkie zapytania.
Czy bez axios można mieć podobny komfort w fetch?
Tak, i w wielu projektach wystarcza kilkanaście linijek własnej funkcji. Przetestowałem ją na lokalnym serwerze:
class HttpError extends Error {
constructor(status, data) {
super(`HTTP ${status}`);
this.status = status;
this.data = data;
}
}
async function fetchJson(url, options = {}) {
const response = await fetch(url, {
signal: AbortSignal.timeout(5000),
...options,
});
const data = await response.json().catch(() => null);
if (!response.ok) throw new HttpError(response.status, data);
return data;
}
Wynik testu: dla poprawnej odpowiedzi funkcja zwróciła { id: 1 }, a dla 401 rzuciła HttpError ze statusem 401 i ciałem { message: 'Brak dostępu' }. Czyli to samo zachowanie co w axios, bez dodatkowej zależności. Cena: ta funkcja jest twoja, więc sam ją utrzymujesz i testujesz.
Czy axios używa dziś fetch w środku?
Tak, można go o to poprosić. Od wersji 1.7.0 (maj 2024) axios ma adapter fetch: zamiast XMLHttpRequest wysyła zapytania natywnym fetch, zachowując swoje API i interceptory. Włączasz go opcją:
const api = axios.create({ adapter: "fetch" });
W teście zapytanie przez ten adapter zwróciło poprawne dane. To pokazuje, w jakim kierunku poszedł projekt: axios przestał być „zamiennikiem XMLHttpRequest”, a stał się wygodną warstwą nad dowolnym transportem.
Kiedy axios, a kiedy fetch?
Moja rekomendacja jest prosta: zacznij od fetch, a po axios sięgnij, kiedy poczujesz konkretny ból, który on rozwiązuje.
| Wybierz | Gdy |
|---|---|
fetch | Kilka prostych zapytań, mała aplikacja, nauka, brak potrzeby wspólnej logiki, chcesz zero zależności |
axios | Wiele zapytań z tym samym tokenem lub obsługą błędów (interceptory), zespół już używa axios, ten sam kod w Node.js i w przeglądarce, wygoda response.data i timeout |
własna funkcja nad fetch | Chcesz kontrolę i brak zależności, a potrzebujesz tylko błędów HTTP i timeoutu |
W starszych projektach axios zostanie jeszcze długo i nie ma sensu go z nich na siłę wyrzucać. Natomiast w nowym, małym projekcie fetch wystarczy, a mniej zależności to mniej do aktualizacji i mniej do pilnowania.
Czy axios jest bezpieczny? Co się stało w marcu 2026 roku?
To argument, o którym warto wiedzieć przy wyborze każdej zależności. 31 marca 2026 roku na npm pojawiły się dwie złośliwe wersje: axios@1.14.1 i axios@0.30.4. Według analiz opublikowanych przez zespoły bezpieczeństwa atakujący przejął konto opiekuna i dodał do pakietu dodatkową zależność, która uruchamiała szkodliwy kod przy instalacji. Samego kodu axios nie zmieniono. Złośliwe wersje usunięto z npm, a ostatnie czyste wydania to 1.14.0 i 0.30.3.
Wniosek nie brzmi „nie używaj axios”, tylko: każda zależność z npm to zaufanie do cudzego konta. Dlatego warto trzymać plik package-lock.json w repozytorium, instalować przez npm ci i nie aktualizować wszystkiego automatycznie w dniu wydania. Mniej zależności oznacza mniejszą powierzchnię ataku, co jest realnym argumentem za fetch w prostych projektach.
Jak axios wypada w pracy z CORS?
Tak samo jak fetch. CORS to mechanizm przeglądarki, a nie biblioteki, więc zmiana z fetch na axios nie naprawi błędu „No 'Access-Control-Allow-Origin' header”. Rozwiązaniem jest konfiguracja serwera. Jak to działa, opisuję w artykule o CORS i nagłówkach HTTP.
Czy warto uczyć się axios w 2026 roku?
Tak, z dwóch powodów. Po pierwsze, spotkasz go w pracy: ok. 145 mln pobrań tygodniowo oznacza, że jest w ogromnej liczbie istniejących projektów, w tym w tych, w których będziesz pracować jako junior. Po drugie, nauka jest tania: jeśli rozumiesz fetch, axios opanujesz w godzinę. Kolejność jest jednak ważna: najpierw zrozum fetch i obietnice, bo to fundament, a axios to tylko wygodna nakładka. Jeśli budujesz aplikację w Reakcie, zobaczysz oba rozwiązania obok siebie.
Najczęstsze pytania
Czy axios jest lepszy od fetch? Nie w każdej sytuacji. Jest wygodniejszy przy wielu zapytaniach i wspólnej logice, ale fetch jest wbudowany i do prostych zastosowań wystarcza.
Czy axios jest jeszcze rozwijany? Tak. Najnowsza wersja na npm to 1.21.0 (październik 2026), a od wersji 1.7.0 ma adapter fetch.
Czy axios działa bez przeglądarki? Tak, w Node.js, z tym samym zapisem co w przeglądarce.
Czy axios powstał, bo przeglądarki różnie obsługiwały zapytania? Nie tak jak jQuery. Powodem była niewygoda XMLHttpRequest i brak obietnic, a nie zgodność przeglądarek.
Czy muszę znać axios, żeby dostać pracę? Nie musisz, ale znajomość fetch i podstaw axios pomoże ci czytać cudzy kod. Rozwijaj ją razem z zaawansowanym JavaScriptem.


