Conditional GET Requests with ETag and If-Modified-Since

Learn how to use conditional request headers like ETag, If-None-Match, and If-Modified-Since to optimize bandwidth and caching.

Best Practices

Detailed Explanation

What Are Conditional Requests?

Conditional requests allow clients to ask the server "has this resource changed since I last fetched it?" If it has not changed, the server returns 304 Not Modified with no body, saving bandwidth.

ETag-Based Conditionals

Step 1: Client fetches the resource and receives an ETag:

GET /api/users/42 HTTP/1.1
Host: api.example.com

HTTP/1.1 200 OK
ETag: "v3-abc123"
Content-Type: application/json

{ "id": 42, "name": "Alice", "version": 3 }

Step 2: Client sends a conditional request with If-None-Match:

GET /api/users/42 HTTP/1.1
If-None-Match: "v3-abc123"

Step 3: Server checks if the ETag matches:

HTTP/1.1 304 Not Modified
ETag: "v3-abc123"

No body is transferred — the client uses its cached copy.

Date-Based Conditionals

GET /api/reports/daily HTTP/1.1
If-Modified-Since: Thu, 15 Jan 2026 10:00:00 GMT

If the resource has not changed since the specified date:

HTTP/1.1 304 Not Modified
Last-Modified: Thu, 15 Jan 2026 10:00:00 GMT

Conditional PUT for Conflict Prevention

ETags are also used with unsafe methods to prevent lost updates:

PUT /api/users/42 HTTP/1.1
If-Match: "v3-abc123"
Content-Type: application/json

{ "name": "Alice Updated", "version": 4 }

If another client has modified the resource (ETag no longer matches):

HTTP/1.1 412 Precondition Failed

This is the HTTP way of implementing optimistic concurrency control.

Conditional Header Summary

Header Used With Purpose
If-None-Match GET, HEAD Skip download if ETag matches
If-Modified-Since GET, HEAD Skip download if not changed since date
If-Match PUT, PATCH, DELETE Prevent update if resource changed
If-Unmodified-Since PUT, PATCH, DELETE Prevent update if modified since date

Use Case

A news reader app checks for article updates every 5 minutes using conditional GET with If-None-Match. Most requests return 304 (no change), consuming minimal bandwidth. Only when an article is actually updated does the full response body transfer.

Try It — HTTP Method Reference

Open full tool