Content-Type — to nagłówek HTTP, który określa, w jakim formacie przesyłane są dane między klientem a serwerem. Bez prawidłowego typu MIME przeglądarka nie może poprawnie przetworzyć odpowiedzi: plik tekstowy wyświetla się jako surowy kod, a obraz nie otwiera się. Według MDN Web Docs, 2025, Content-Type jest obowiązkowy do prawidłowego przesyłania danych dowolnego typu w protokole HTTP i określa, jak odbiorca interpretuje treść wiadomości.
Najważniejsze
Content-Type — to nagłówek HTTP z grupy nagłówków reprezentacji (representation headers), który informuje odbiorcę o formacie danych w treści wiadomości. Jest obowiązkowy dla żądań i odpowiedzi HTTP zawierających treść (body), a bez niego klient nie może poprawnie zinterpretować otrzymanych bajtów. Przeglądarka lub aplikacja mobilna na podstawie Content-Type wybiera parser: dla text/html uruchamia silnik HTML, dla image/png — dekoder PNG, dla application/json — parser JSON.
Wartość Content-Type to typ MIME — standaryzowany identyfikator formatu danych. Skrót MIME oznacza Multipurpose Internet Mail Extensions, ponieważ standard ten został pierwotnie stworzony dla załączników e-mail. Stał się jednak podstawą HTTP i jest dziś używany powszechnie — od przesyłania stron internetowych po wymianę danych w REST API. Każdy typ MIME składa się z dwóch części: głównej kategorii i uszczegóławiającego podtypu, rozdzielonych ukośnikiem.
Parametr charset uzupełnia Content-Type dla formatów tekstowych. Na przykład Content-Type: text/html; charset=utf-8 oznacza, że przesyłany jest dokument HTML w kodowaniu UTF-8. Według IETF RFC 7231, sekcja 3.1.1.5, nagłówek Content-Type jest obowiązkowy dla wiadomości HTTP zawierających treść, a jego brak jest interpretowany jako application/octet-stream lub prowadzi do MIME sniffing.
Protokół HTTP/0.9, wydany w 1991 roku, przesyłał tylko strony HTML, więc typ danych był domyślnie określony. Wraz z pojawieniem się HTTP/1.0 w specyfikacji RFC 1945 twórcy zdali sobie sprawę z konieczności przesyłania obrazów, arkuszy stylów i skryptów. Zaadaptowali standard MIME z protokołu e-mail, a Content-Type stał się nieodłączną częścią HTTP. Od tego czasu rejestr IANA rozszerzył się do setek wartości — od znanych text/html po współczesne image/avif i application/manifest+json.
Content-Type odgrywa kluczową rolę w ochronie przed atakami. Jeśli serwer wysyła plik HTML z typem MIME text/plain, przeglądarka nie będzie wykonywać JavaScript i budować DOM — zapobiega to atakom XSS. Nagłówek X-Content-Type-Options: nosniff, zalecany przez OWASP, całkowicie zabrania przeglądarce zgadywania typu MIME na podstawie zawartości. Według PortSwigger Research, ataki z wykorzystaniem MIME sniffing były szczególnie rozpowszechnione w Internet Explorer 6-9, gdzie przeglądarka ignorowała Content-Type i określała typ na podstawie pierwszych bajtów pliku.
Typ MIME jest określany w formacie type/subtype, gdzie type to ogólna kategoria danych, a subtype to konkretny format w jej obrębie. Na przykład w wartości image/png kategoria image wskazuje na obraz, a podtyp png — na format Portable Network Graphics. Kategorii jest zaledwie kilka: text, image, audio, video, application, multipart i message. Resztę różnorodności zapewniają podtypy, których są setki.
Dodatkowe parametry są przekazywane przez średnik po podtypie. Najpopularniejszym parametrem jest charset do określania kodowania. Content-Type: application/json; charset=utf-8 informuje, że przesyłany jest dokument JSON w kodowaniu UTF-8. Formalnie charset dla application/json jest zbędny, ponieważ JSON zawsze jest w UTF-8 zgodnie ze specyfikacją RFC 8259, ale jawne określenie poprawia kompatybilność ze starymi klientami HTTP.
| Kategoria | Przykłady podtypów | Opis |
|---|---|---|
| text | html, plain, css, javascript, csv | Formaty tekstowe czytelne dla człowieka |
| image | jpeg, png, gif, webp, svg+xml, avif | Obrazy rastrowe i wektorowe |
| audio | mpeg, ogg, wav, mp4, webm | Formaty audio do strumieniowego odtwarzania |
| video | mp4, webm, ogg, x-msvideo, 3gpp | Formaty wideo i kontenery multimedialne |
| application | json, xml, pdf, zip, octet-stream, protobuf | Dane binarne i strukturyzowane |
| multipart | form-data, mixed, alternative, byteranges | Dokumenty złożone z wielu części |
Standardowe typy MIME są rejestrowane w rejestrze IANA i mają prefiks głównej kategorii. Niestandardowe (vendor-specific) używają prefiksu x- lub formatu vnd.company.type — na przykład application/vnd.google-earth.kml+xml dla formatu KML od Google. Przeglądarki mogą nie rozpoznawać niestandardowych typów, dlatego dla nieznanych załączników używany jest application/octet-stream — uniwersalny strumień binarny, którego przeglądarka nie próbuje wyświetlić, ale oferuje pobranie jako pliku.
Parametr charset jest krytyczny dla poprawnego wyświetlania tekstu. Bez niego przeglądarka może nieprawidłowo zinterpretować znaki, co prowadzi do krzaków (mojibake). Dla sieci standardem jest UTF-8, ale spotyka się ISO-8859-1 (Latin-1) dla języków zachodnioeuropejskich i windows-1251 dla cyrylicy na starych stronach. Zalecenie W3C — zawsze określać charset=utf-8 dla text/html i text/plain, a dla application/json charset nie jest wymagany.
W praktyce twórcy stron internetowych i programiści mobilni pracują z ograniczonym zestawem typów MIME. Znajomość tych typów jest niezbędna do prawidłowej konfiguracji serwera, pisania klientów HTTP i obsługi plików statycznych. text/html — podstawowy typ dla stron internetowych, zwracany domyślnie przez serwery Apache i Nginx dla plików HTML. application/xhtml+xml jest używany rzadziej i tylko dla dokumentów XHTML.
application/json stał się standardem dla REST API. Serwery zwracają dane JSON z tym typem MIME, a klienci wysyłają go w żądaniach POST i PUT. text/javascript (przestarzały) i application/javascript są używane dla plików JavaScript. Według W3Techs Survey, 2025, JSON jest najszybciej rosnącym formatem danych w sieci, wyprzedzając XML w 2018 roku. Dla usług SOAP wciąż stosuje się text/xml lub application/soap+xml.
Dla obrazów typ MIME jest określany przez format pliku: image/jpeg dla JPEG, image/png dla PNG, image/gif dla GIF, image/webp dla nowoczesnego formatu WebP. image/svg+xml jest używany dla grafiki wektorowej i obsługuje osadzone style i skrypty. video/mp4, audio/mpeg i application/pdf — inne często spotykane typy. Dla czcionek internetowych używa się font/woff2, font/woff i font/ttf.
Przy wysyłaniu plików przez formularz HTML używany jest multipart/form-data — złożony typ MIME, który dzieli żądanie na kilka części. Każda część ma własny nagłówek Content-Type i Content-Disposition, wskazujący nazwę pola i oryginalną nazwę pliku. Serwer otrzymuje plik z jego rzeczywistym typem MIME, określonym przez przeglądarkę, i może go zweryfikować po stronie backendu. application/octet-stream jest stosowany dla plików nieznanego typu — przeglądarka nie próbuje wyświetlić zawartości, ale oferuje zapisanie jej na dysku.
Typ MIME wpływa na politykę buforowania CDN i przeglądarki. Obrazy ze stabilnymi URL-ami są zwykle buforowane na długi okres (rok i dłużej), podczas gdy strony HTML — na minuty lub sekundy. Serwery CDN Cloudflare i Akamai używają Content-Type do wyboru algorytmu kompresji: text/* jest kompresowany gzip lub brotli, image/* — nie, ponieważ obrazy są już skompresowane. Prawidłowa konfiguracja Content-Type na serwerze bezpośrednio wpływa na wydajność ładowania stron i aplikacji mobilnych.
Serwer ustawia nagłówek Content-Type w odpowiedzi HTTP na podstawie typu żądanego pliku lub dynamicznie wygenerowanej treści. Popularne serwery www Nginx i Apache mają wbudowane tablice typów MIME, które mapują rozszerzenie pliku na odpowiedni Content-Type. Na przykład plik index.html otrzymuje text/html, a style.css — text/css. Dla odpowiedzi dynamicznych programista określa Content-Type w kodzie aplikacji w PHP, Python, Java lub Kotlin.
Klient używa Content-Type do wyboru obsługi. Jeśli serwer zwraca text/html, przeglądarka uruchamia parser HTML i buduje drzewo DOM. Jeśli image/png — uruchamia dekoder PNG. Jeśli Content-Type jest nieobecny lub nieprawidłowy, klient stosuje MIME sniffing — próbuje odgadnąć typ na podstawie sygnatury (magic bytes) na początku pliku. JPEG zaczyna się od bajtów FF D8 FF, PNG — od 89 50 4E 47, a PDF — od 25 50 44 46. Ten proces jest potencjalnie niebezpieczny i wyłączany przez nagłówek X-Content-Type-Options: nosniff.
W aplikacjach mobilnych Content-Type jest obsługiwany przez klientów HTTP. OkHttp na Androidzie automatycznie analizuje nagłówek Content-Type z odpowiedzi i udostępnia go przez metodę Response.header("Content-Type"). Klient iOS URLSession robi to samo przez właściwość URLResponse.mimeType. Na obu platformach Content-Type jest używany do wyboru parsera: JSON — przez Moshi lub Gson na Androidzie, przez Codable na iOS; obrazy — przez Glide, Coil lub SDWebImage.
Content negotiation (negocjowanie treści) — mechanizm HTTP, w którym klient określa żądany format odpowiedzi przez nagłówek Accept, a serwer wybiera odpowiedni format i zwraca go z odpowiednim Content-Type. Na przykład klient wysyła Accept: application/json, serwer odpowiada Content-Type: application/json. Jeśli serwer nie może dostarczyć żądanego formatu, zwraca 406 Not Acceptable. W REST API ten mechanizm pozwala jednemu endpointowi zwracać dane w JSON, XML lub HTML.
Nagłówek Content-Type jest używany zarówno w żądaniach HTTP (Request), jak i odpowiedziach HTTP (Response). W żądaniach określa format treści żądania, na przykład przy wysyłaniu JSON przez POST. W odpowiedziach — format zwracanych danych. Zasadnicza różnica polega na tym, że Content-Type żądania ustawia klient, a Content-Type odpowiedzi — serwer. Nieprawidłowe ustawienie Content-Type w żądaniu powoduje, że serwer nie może sparsować treści, zwracając błąd 400 Bad Request lub 415 Unsupported Media Type.
W żądaniach HTTP Content-Type jest obowiązkowy dla metod POST, PUT i PATCH, jeśli żądanie zawiera treść (body). GET, HEAD i DELETE zazwyczaj nie używają treści, więc Content-Type dla nich nie jest określany lub jest ignorowany. Przy wysyłaniu formularza HTML z atrybutem enctype="multipart/form-data" przeglądarka automatycznie ustawia Content-Type: multipart/form-data z unikalnym łańcuchem granicznym (boundary), który rozdziela części złożonego żądania. Każda część jest oddzielana przez --boundary, a koniec żądania oznaczany przez --boundary--.
W odpowiedziach HTTP Content-Type jest ustawiany przez serwer. Jeśli serwer nie określa Content-Type, klient albo włącza MIME sniffing, albo przetwarza odpowiedź jako application/octet-stream. Metoda HTTP HEAD pozwala uzyskać nagłówki odpowiedzi, w tym Content-Type, bez przesyłania treści. Jest to przydatne do sprawdzenia typu zasobu przed jej pełnym załadowaniem. Serwery CDN mogą nadpisywać Content-Type przy transformacji treści — na przykład przy konwersji obrazów do WebP.
import okhttp3.*
fun checkContentType() {
val client = OkHttpClient()
val request = Request.Builder()
.url("https://api.example.com/resource")
.head()
.build()
client.newCall(request).execute().use { response ->
val contentType = response.header("Content-Type")
val mediaType = MediaType.parse(contentType)
println("Rodzaj: ${mediaType?.type}, Podtyp: ${mediaType?.subtype}")
}
}
W programowaniu mobilnym nagłówek Content-Type jest obsługiwany automatycznie przez klientów HTTP. W OkHttp na Androidzie Content-Type jest ustawiany przez RequestBody: val body = "{}".toRequestBody("application/json".toMediaType()). Retrofit zarządza Content-Type przez adnotacje: @Body dla JSON, @Part dla multipart. Na iOS URLSession ustawia Content-Type dla HTTPBody, a Alamofire robi to przez parametr encoding: JSONEncoding.default lub URLEncoding.default. Ręczne ustawienie Content-Type jest wymagane przy pracy z surowymi gniazdami lub niestandardowymi protokołami.
Nieprawidłowy Content-Type — jeden z najczęstszych problemów przy tworzeniu i integracji usług internetowych. Najczęstszym błędem jest sytuacja, gdy serwer zwraca text/html zamiast application/json. Klient otrzymuje JSON jako ciąg HTML, nie może go sparsować i zgłasza wyjątek. Dzieje się tak, gdy framework webowy jest skonfigurowany domyślnie na HTML, a programista zapomina nadpisać Content-Type dla endpointu API. W PHP objawia się to brakiem header('Content-Type: application/json'), w Spring Boot — brakiem adnotacji produces.
Drugim co do częstotliwości błędem jest nieprawidłowy lub brakujący charset. Jeśli serwer wysyła text/html; charset=iso-8859-1, a przeglądarka oczekuje UTF-8, znaki cyrylicy wyświetlają się jako krzaki. Ten problem jest charakterystyczny dla starych stron, które nie przeszły na UTF-8. Dla JSON taki błąd występuje rzadziej, ponieważ RFC 8259 nakazuje UTF-8 bez dodatkowego uzgadniania. Rozwiązanie — zawsze jawnie określać charset=utf-8 dla tekstowych typów MIME w konfiguracji serwera.
Trzeci problem — niezgodność Content-Type z rzeczywistą zawartością. Jeśli serwer wysyła Content-Type: image/png, a treść odpowiedzi zawiera obraz WebP, przeglądarka może go nie dekodować. Serwery CDN czasami kompresują obrazy ze zmianą formatu, ale nie aktualizują nagłówka Content-Type. Sprawdzenie zgodności Content-Type z rzeczywistą zawartością — obowiązkowy etap testowania API i testów integracyjnych aplikacji mobilnych.
Do debugowania używaj narzędzi deweloperskich przeglądarki (zakładka Network), curl z flagą -I do sprawdzania nagłówków odpowiedzi lub snifferów ruchu typu Charles Proxy i Wireshark. Nginx konfiguruje się przez dyrektywę include mime.types, Apache — przez AddType i AddDefaultCharset. Dla plików statycznych zawsze sprawdzaj, czy rozszerzenie pliku odpowiada jego typowi MIME. Dla odpowiedzi dynamicznych we wszystkich językach programowania jawnie ustawiaj Content-Type przed wypisaniem danych — zapobiega to zdecydowanej większości problemów.
Często zadawane pytania
Bez Content-Type przeglądarka włącza MIME sniffing — analizę pierwszych bajtów odpowiedzi w celu automatycznego określenia typu danych. Może to prowadzić do nieprawidłowego przetwarzania treści i tworzyć luki bezpieczeństwa. Nowoczesne przeglądarki z nagłówkiem X-Content-Type-Options: nosniff całkowicie blokują zgadywanie.
Content-Type określa format danych przesyłanych w bieżącej wiadomości (treści żądania lub odpowiedzi). Accept — to nagłówek żądania, który informuje serwer, jaki format odpowiedzi preferuje klient. Content-Type ustawia nadawca danych, a Accept — odbiorca, i uczestniczą one w mechanizmie negocjowania treści.
Oficjalny typ MIME dla JSON — application/json zgodnie ze specyfikacją RFC 8259. Wcześniej używany był text/x-json, ale ten typ jest przestarzały. Parametr charset dla application/json nie jest potrzebny, ponieważ JSON zgodnie ze specyfikacją jest zawsze przesyłany w kodowaniu UTF-8, UTF-16 lub UTF-32 z automatycznym wykrywaniem kolejności bajtów (BOM).
Dzieje się tak, gdy framework webowy nie nadpisuje domyślnego Content-Type dla endpointów API. W PHP naprawia się to wywołaniem header('Content-Type: application/json'), w Spring Boot — adnotacją @GetMapping(produces = "application/json"), w Express.js — metodą res.set('Content-Type', 'application/json').
application/octet-stream — uniwersalny typ MIME dla danych binarnych, których format jest nieznany. Przeglądarka nie próbuje wyświetlić takiego pliku w oknie, ale oferuje zapisanie go na dysku. Jest używany do pobierania plików, załączników e-mail i danych strumieniowych, gdy serwer nie może określić dokładnego typu przesyłanej treści.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również