// Engineering Log
HTTP, HTTPS and TLS: Part 1 — What is HTTP: requests, responses, methods and status codes
Published on 2026-09-25
// Fast route
This article belongs to the topic Networking and routing.
HTTP (HyperText Transfer Protocol) — an application-layer protocol by which a browser, mobile app, or script requests a resource from a server and receives a response. A resource can be an HTML page, an image, JSON from an API, or a file to download. HTTP is stateless between requests: the server handles each request separately, and “memory” about the user — session, cart, login state — is provided by cookies and tokens that the client sends in headers.
Currently HTTP is specified by a set of IETF documents from 2022: RFC 9110 defines the general semantics (methods, codes, headers), and RFC 9112, 9113, and 9114 — the wire formats for HTTP/1.1, HTTP/2, and HTTP/3. Semantics are the same across versions; only how bytes travel on the wire differs. Therefore everything written in this section applies to any version.
How the exchange looks
The client opens a TCP connection to the server (port 80 for HTTP, 443 for HTTPS), sends a request, and waits for a response. In HTTP/1.1 this is plain text, which is convenient to inspect with curl -v:
curl -v http://example.com/Lines with > are what curl sent, with < — the server response:
> GET / HTTP/1.1
> Host: example.com
> User-Agent: curl/8.7.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/html
< Content-Length: 1256
< Cache-Control: max-age=3600
<
<!doctype html>
...What a request consists of
- Start line: method, path, and protocol version —
GET /catalog?page=2 HTTP/1.1. The path includes the query string (?page=2), but does not include the fragment (#section) — the browser does not send the fragment to the server. - Headers:
Name: valuepairs, one per line. OnlyHostis mandatory — the server uses it to determine which site on this IP address the client wants. - An empty line — end of headers.
- Body — optional. It is sent by methods that transmit data: POST, PUT, PATCH. The server learns the body length from the
Content-Lengthheader or from chunked transferTransfer-Encoding: chunked.
Header name case is not significant: Content-Type and content-type are the same header. In HTTP/2 and HTTP/3 header names are always sent in lowercase.
What a response consists of
- Status line: version, code, and a reason phrase —
HTTP/1.1 404 Not Found. The phrase is for humans; programs look at the code; in HTTP/2 and HTTP/3 the phrase is absent. - Response headers: content type, length, caching rules, cookies, security headers.
- Empty line and body.
Methods
The method tells the server what the client wants to do with the resource. RFC 9110 defines eight methods; another one (PATCH) is defined by RFC 5789.
| Method | Purpose | Safe | Idempotent | Request body |
|---|---|---|---|---|
| GET | retrieve a resource | yes | yes | not used |
| HEAD | same as GET but only headers | yes | yes | no |
| POST | submit data for processing: form, create an object | no | no | yes |
| PUT | create or fully replace a resource at the address | no | yes | yes |
| PATCH | partially modify a resource | no | no | yes |
| DELETE | delete a resource | no | yes | usually no |
| OPTIONS | discover which methods are available; used in CORS | yes | yes | usually no |
| CONNECT | open a tunnel through a proxy, most often for HTTPS | no | no | no |
| TRACE | return the request back for debugging; usually disabled on servers | yes | yes | no |
A safe method does not change server state: it can be called any number of times without breaking anything. That’s why search engine crawlers and browser prefetch functions freely follow links — links always point to GET. If deleting a record in an admin panel is implemented as GET /delete?id=5, sooner or later some crawler or antivirus that checks links in emails will execute it.
An idempotent method yields the same result when repeated. PUT /users/5 with the same body twice will leave the user in the same state, while two identical POST /orders will create two orders. This matters for retries: clients, proxies, and load balancers are allowed to retry an idempotent request after a connection failure, but not POST. Hence the browser warning “Resubmit form data?” when refreshing a page after POST.
A body in GET is not forbidden by the spec, but it makes no sense by the standard, and many proxies and servers drop it. GET parameters are passed in the query string.
Status codes
A code is a three-digit number; the first digit indicates the class.
1xx — informational. Interim responses after which a final response will come.
100 Continue— the server is ready to receive a large body (the client asks about this with theExpect: 100-continueheader; curl adds it automatically when sending large bodies);101 Switching Protocols— the server switches to another protocol, for example WebSocket (more — “Switching to HTTPS and the Upgrade header”);103 Early Hints— early hints: the server is still preparing the page but already tells which styles and scripts should be started loading.
2xx — success.
200 OK— a normal successful response;201 Created— resource created; its address is in theLocationheader;204 No Content— success, no body (common response to DELETE and PUT);206 Partial Content— part of a file was returned per aRangerequest; resuming downloads and video seeking work on this.
3xx — redirects. The address to go to is in the Location header.
301 Moved Permanentlyand308 Permanent Redirect— the resource has moved permanently; search engines transfer page weight to the new address, browsers remember the redirect;302 Foundand307 Temporary Redirect— temporary redirect;304 Not Modified— the resource has not changed; the cached copy can be used.
The difference between 301/302 and 308/307 is in the method: historically browsers convert POST to GET on 301 and 302 and lose the body, while 307 and 308 require repeating the request with the same method and same body. For redirects of APIs or forms use 307/308.
4xx — client error. The request is wrong; repeating it without changes is pointless.
400 Bad Request— syntactically invalid request, malformed JSON;401 Unauthorized— authentication required (despite the name, it means the client did not present credentials); the server sends aWWW-Authenticateheader with the authentication method;403 Forbidden— the client is known but has no access;404 Not Found— resource not found;405 Method Not Allowed— method not supported for this address;408 Request Timeout— the client took too long to transmit the request;409 Conflict— conflict with the current state, e.g., object version is outdated;413 Content Too Large— body larger than allowed (in Nginx —client_max_body_size, default 1 MB);415 Unsupported Media Type— the server does not accept thisContent-Type;429 Too Many Requests— rate limit triggered; aRetry-Afterheader may indicate how long to wait;451 Unavailable For Legal Reasons— access blocked due to legal demand.
5xx — server error. The request is fine, something broke on the server side.
500 Internal Server Error— an unhandled error in the application;502 Bad Gateway— a proxy or load balancer did not get a valid response from the upstream application: the app crashed, closed the connection, or returned garbage;503 Service Unavailable— the service is temporarily unavailable: overload, maintenance;504 Gateway Timeout— the proxy did not wait long enough for the application.
Codes 502 and 504 are almost always returned not by the application itself but by the fronting Nginx, HAProxy, or CDN. If you see 502, check the proxy logs — there will be a reason like connect() failed (111: Connection refused) while connecting to upstream.
URL and what is sent to the server
The address https://user@shop.example.ru:8443/catalog/phones?sort=price#reviews is parsed like this:
https— scheme, it defines the protocol and default port;user@— user info; browsers no longer support it; curl turns it into anAuthorizationheader;shop.example.ru— host, it is resolved to an IP via DNS and sent inHost(and with HTTPS also in SNI);8443— port, if it is non-standard;/catalog/phones— path;sort=price— query string;reviews— fragment, it stays in the browser.
Non-ASCII characters and reserved characters in paths and parameters are percent-encoded: space — %20, the Cyrillic letter “я” — %D1%8F. A Cyrillic domain is encoded differently — in Punycode (пример.рф → xn--e1afmkfd.xn--p1ai), and it is in that form that it goes to DNS and to Host.
Connections and keep-alive
In HTTP/1.0 a new TCP connection was opened for each request. In HTTP/1.1 the connection remains open by default and subsequent requests go over the same connection: you don’t need to repeat the three-way TCP handshake and, for HTTPS, the TLS handshake. To close the connection after the response send the Connection: close header.
Requests over a single HTTP/1.1 connection are strictly sequential: the next request can be sent only after the previous response. That’s why browsers open up to six parallel connections to the same site. HTTP/2 and HTTP/3 solved this problem.
HTTP and HTTPS
HTTPS is the same HTTP but transmitted inside an encrypted TLS connection. The request and response look the same, transport changes: first client and server agree on keys and verify a certificate, and only then HTTP messages go over the secure channel. Without TLS everything above — address, cookies, passwords from forms, page content — can be seen and modified by any node on the path: cafe Wi-Fi, ISP, proxy.
Try it yourself
HTTP/1.1 is a text protocol, and a request can be typed manually, without a browser or curl. The commands below work on Linux and macOS.
HTTP request using nc. Each line ends with \r\n; after headers — an empty line. sleep is needed so that nc does not close the connection before the response arrives:
{ printf 'GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n'; sleep 2; } | nc example.com 80 | head -6HTTP/1.1 200 OK
Date: Thu, 24 Sep 2026 04:54:21 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: close
Server: cloudflareRemove the Host line — the server will respond 400 Bad Request: without it it doesn’t know which site you want.
The same request over HTTPS. openssl s_client establishes a TLS connection and passes input into it as-is:
printf 'HEAD / HTTP/1.1\r\nHost: example.ru\r\nConnection: close\r\n\r\n' \
| openssl s_client -quiet -connect example.ru:443 -servername example.ru 2>/dev/nullMethods and status codes. See how your site responds to different methods and to a non-existent address:
curl -s -o /dev/null -w '%{http_code}\n' https://example.ru/ # 200
curl -s -o /dev/null -w '%{http_code}\n' https://example.ru/no-such-page/ # should be 404, not 200
curl -s -o /dev/null -w '%{http_code}\n' -X DELETE https://example.ru/ # 405 or 403
curl -si -X OPTIONS https://example.ru/ | grep -iE '^(HTTP|allow)' # which methods are allowed
curl -s -o /dev/null -w '%{http_code} -> %{redirect_url}\n' http://example.ru/ # 301 to httpsIf a site responds 200 with a “Not Found” page for a non-existent address, search engines consider such pages real and index them — this is called a soft 404, and Google Search Console marks such pages separately.
The HTTP request from curl itself. With the -v flag you can see which headers curl added itself — compare them with what the browser sends (DevTools → Network → Headers → Request Headers):
curl -sv -o /dev/null https://example.ru/ 2>&1 | grep '^>'Common mistakes
- Changing data via GET — a crawler or prefetch will perform the action without the user’s knowledge.
- Redirecting forms and APIs with 301/302 — POST body is lost. Use 307 or 308.
- 200 with an error message in the body instead of a 4xx/5xx code — monitoring and caches consider the response successful; a CDN may cache the error page.
- 401 instead of 403 and vice versa — the client cannot tell whether it needs to log in or logging in won’t help.
- Automatic retry of POST in your own client after a timeout — duplicate orders and payments. For safe retries use an idempotency key in a header (payment APIs do this).
// Similar task
If you are dealing with something similar
This article belongs to one of the main working topics. You can keep reading on the topic, go to the homepage to understand what I do, or open the service pages directly.
Article topic
Networking and routing
MikroTik, VPN, routing, DNS, BGP, connectivity, and access troubleshooting.
Typical tasks behind this topic
- Set up VPN and secure access to office or cloud
- Fix routing, DNS, or unstable connectivity
- Configure MikroTik, firewall, and external links
// Next step
If you need help with this topic, not just another article, it is better to go straight to the service page. The homepage and topic collection stay available as secondary routes.
Open services// Reviews
Related reviews
Huge thanks to Mikhail for the work — I'm very pleased with the result. Special thanks for his recommendations during setup: from my rather muddled brief (I know little about servers), Mikhail, through clarifying questions and suggestions, formed a clear understanding of what the final build would accomplish and how best to organize everything. I recommend him!
Many thanks to Mikhail for the work, I am very pleased with the result. I especially thank him for the recommendations during the setup process — from my rather muddled brief (and I know little about servers) Mikhail, …
MikroTik hAP router setup. I'll set up a MikroTik Wi‑Fi router for you.
2025-07-21 · ★ 5/5
An excellent specialist, a savvy expert, and a wonderful person. In an hour he fixed what we'd been racking our brains over for days! I'm sure this won't be the last time we rely on his boundless professionalism.
An excellent specialist, a savvy expert, and a wonderful person. In an hour he fixed for us what we had been scratching our heads over for days! I'm sure this won't be the first time we make use of his boundless …
MikroTik hAP router setup. I'll configure a MikroTik Wi-Fi router for you.
2025-05-28 · ★ 5/5
A professional approach to the job!
Professional approach to the job!
MikroTik hAP router setup. I'll set up a MikroTik Wi-Fi router for you.
2025-03-31 · ★ 5/5
Knows their stuff, gets things done. Everything was prompt and to the point; I was satisfied with the collaboration.
Knows, can, does. Everything was prompt and to the point; I was satisfied with the collaboration.
MikroTik hAP router setup. I'll set up a MikroTik Wi‑Fi router for you.
2025-03-14 · ★ 5/5
Thanks! We set up the router according to my technical specification, with a full explanation of what we're doing.
Thank you! The router was configured according to my technical specification, with a full explanation of what we are doing
MikroTik hAP router setup. I'll configure a MikroTik Wi‑Fi router for you.
2025-03-09 · ★ 5/5
Everything's great! Thanks! I recommend it.
Everything's great! Thank you! I recommend it
// Contact
Need help?
Get in touch with me and I'll help solve the problem
I reply within one business day (03:00-13:00 GMT)
Или оставьте заявку здесь:
// Related