How applications communicate
An address tells a client where to send a request. HTTP defines how that request is expressed and how the server answers. Reading these exchanges explains what happens when an application loads data, submits a sign-in form or follows a redirect.
HTTP: requests and responses
A client and server communicate by exchanging messages. The client needs a way to specify what it wants, and the server needs a way to return a result the client can understand. This applies to reading data as well as asking the service to make a change.
Ava chooses an album. Her browser sends a request asking for it, and the photo service sends a response. Loading a photograph or saving a caption can cause further exchanges.
Both sides follow a protocol, agreed rules for the messages. The web uses HTTP, the Hypertext Transfer Protocol. HTTPSHTTP protected by TLS, so traffic is encrypted and checked for changes while it travels. It protects the connection, but does not prove that the site at the other end is honest. carries those messages over the protected connection introduced in Clients, servers, and addresses.
Programs use these exchanges too. An API describes the operations a service exposes to software, and an endpoint is an address at which it accepts a particular kind of request.
Reading a request
Here is an illustrative HTTP/1.1 request for an album. The domain is fictional, and this example doesn't send anything. HTTP/2 and HTTP/3 carry the same kinds of information in different formats.
GET /albums/42 HTTP/1.1
Host: photos.example
Accept: application/jsonGET is the method, which describes the requested operation. Here it asks to retrieve the resource at the path /albums/42. The following lines are headers, each a name and a value: Host: photos.example identifies the host the request is for, and Accept asks for JSON. JSON is a text format for structured data that writes names and values inside braces, such as {"title":"Weekend walks"}.
Reading a response
The album service might answer with the following message.
HTTP/1.1 200 OK
Content-Type: application/json
{"id":"42","title":"Weekend walks"}The status code summarizes the outcome. Headers describe the response, and the body carries data such as the album's identifier and title.
Read the status in context. A 401 means valid authenticationChecking evidence that someone, or some application, controls an account, such as a password or a passkey. It establishes which account is being used, not what that account may do. credentials are missing or were not accepted; a 403 means the request is refused. A service may use 404 for a private resource it doesn't want to reveal, so “not found” needn't prove that no such record exists.
A request for protected data has to carry a credential the service will accept. Programs calling an API usually send it in an Authorization header, and it is often a token: a value issued by a service the API trusts, standing for the access the caller has been given. A token that lets a caller use an API is an access token. Most access tokens are bearer tokens, which means that whoever presents one can use it, much like a ticket at a door. A copied bearer token works for the person who copied it, so it needs the same care as a password.
When the credential is missing or not accepted, the API answers 401 and adds a WWW-Authenticate header naming the kind of credential it expects.
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="photos"Bearer tells the calling program to send a bearer token, and realm names the protected area. A program can read that and fix its request. It has no sign-in page to fill in, so the challenge is the useful answer.
Optional detail: Common status codes
| Code | Meaning |
|---|---|
200 | Success. The body holds what was asked for. |
302, 303 | Go to another address, named in the response's Location header, with a new request. |
400 | The request itself is wrong, such as a missing or malformed value, so the server will not act on it. |
401 | The request lacks valid authentication credentials for this resource. |
403 | The server understood the request and refuses it, often because the person asking is not allowed to do this. |
404 | The server did not find the resource or will not disclose it. |
500 | Something failed on the server's side. |
Sending information
Saving a change or signing in requires the client to supply information. A POST request can submit a form for the server to process, with values in its body rather than its URLA web address, such as https://photos.example/api/albums/42?limit=10. It names how to connect (https), the domain, the path to a particular page or resource, and any extra parameters after the question mark..
That placement matters for a password. URLs are easily copied into history, logs and shared links. A request body avoids those URL copies, but still needs HTTPS and careful handling at the receiving service.
A browser submitting a simple sign-in form sends something like this. The values are placeholders, and the block does not send a request.
POST /sign-in HTTP/1.1
Host: photos.example
Content-Type: application/x-www-form-urlencoded
email=ava%40example.com&password=EXAMPLE_ONLYContent-Type describes the format of the body. In this format, each field is a name and a value joined by =, and the fields are separated by &, just like the values in a query. That causes trouble if a value contains one of those symbols itself: a password such as cats&dogs would look like the end of one field and the start of another.
To keep values intact, the browser leaves letters, digits and a few punctuation marks as they are and writes most other characters as % followed by a two-character code. A space is the usual exception: forms write it as +. The @ in Ava's email address becomes %40, and the server turns it back into @ when it reads the form. This is the same percent-encoding that keeps query values intact in an address.
Many APIs follow a style called REST. Each address names a resource, such as an album, and the method says what to do with it. The same address can receive different methods.
| Request | What it asks the server to do |
|---|---|
GET /albums/42 | Return the album. Nothing changes. |
POST /albums | Process the data in the body, here by creating a new album. The sign-in form above also uses POST. |
PUT /albums/42 | Replace the whole album with the version in the body. |
PATCH /albums/42 | Change only the parts named in the body, such as the title. |
DELETE /albums/42 | Remove the album. |
The method states what the client wants, not what it is allowed to do. Anyone can send DELETE /albums/42, so the server must check whether this account may delete this album before it acts.
Following a redirect
Suppose Ava opens a private page before signing in. The service can answer with a redirect: a response whose status code starts with 3, often written 3xx, and a Location header naming another address. The browser makes a new request there.
Redirects are how one website hands a browser to another service and gets it back. Suppose the photo service keeps its sign-in at a separate service, accounts.photos.example. When Ava opens a private album, the photo service redirects her browser there, often with a return destination in the query. After she signs in, the sign-in service redirects her browser back to the photo service, carrying a short result that says the sign-in succeeded.
API requests usually work differently. A program can't fill in a sign-in page, so an API that receives a request without valid credentials returns 401 Unauthorized with its WWW-Authenticate challenge, and the calling program handles the authentication problem itself.
Messages that travel through the browser, like those two redirects, use the front channel. The browser carries them, and whoever controls the browser can read or change them on the way. A request that one service sends straight to another, such as the photo service asking the sign-in service to confirm that result, uses the back channel and never passes through the browser. Because the front channel has that extra participant, the receiving service must validate what arrives rather than trust that it came through an expected-looking page.
A service can also send a larger message through the browser by returning a page with a form that submits itself with POST, putting the message in the form body. Moving the message out of the URL doesn't move it out of the browser: it is still a front-channel exchange.
Optional detail: The redirect as HTTP messages
GET /albums/42 HTTP/1.1
Host: photos.example
Accept: text/htmlHTTP/1.1 302 Found
Location: /sign-inThe Location value supplies the address for a new request. This one is a relative address: it gives only a path, so the browser keeps the same scheme and host and asks for https://photos.example/sign-in.
Connecting separate requests
After a service accepts a sign-in form, it can redirect the browser back to the requested page. The browser retrieves that page with a new request. The earlier password submission and the later page request are separate exchanges, even when they happen moments apart.
The redirect made Ava's journey look continuous, but HTTP does not automatically attach the meaning “this is the person who just signed in” to that later request. The application needs a way to connect the later request to the accepted sign-in, and that continuity is called a session. Most websites keep it with a cookie, a small value the browser stores and sends back with each later request to the site. It must also check whether that account may access the requested resource; remembering a sign-in does not grant every permission.
Optional detail: Why a form response may use 303
303 See Other directs a retrieval request after the form submission, normally GET in this journey, without resending the password body. 307 and 308 preserve the method and body. With 302, a client is allowed to change POST to GET. Choosing the code matters when the original body contains a credential.
Check your understanding
Try these questions before moving on. If an answer isn't right, use the feedback and try again.
Try it in the Lab
- Follow the messages behind Ava's sign-inRead a successful response and an API refusal, then follow a sign-in form through its redirect and history.