Conditional GET: What It Is, the Conditional Request Mechanism

Author: IT Sectr Published: 2026-06-14 Reading time: 7 min

“Conditional GET” — an HTTP mechanism that allows a client to check the relevance of a cached resource before a full download. The client sends a GET request with “If-None-Match” (containing ETag) or “If-Modified-Since” (containing a date) headers, and the server returns 304 Not Modified without a response body if the resource has not changed. According to MDN Web Docs, 2025, conditional requests reduce server and client network traffic. 304 Not Modified is a key HTTP status for efficient mobile application synchronization.

Key Takeaways

  • Conditional GET — an HTTP request with “If-None-Match” or “If-Modified-Since” headers to check cache relevance.
  • 304 Not Modified — a server response indicating the resource has not changed. No response body is sent, saving traffic.
  • If-None-Match — a header with an ETag (version hash), providing precise content-level validation.
  • If-Modified-Since — a header with the last modified date, simpler to implement but less precise (1-second resolution).
  • Efficiency — Conditional GET reduces data transfer during synchronization by 80–95% for unchanged resources.

What Is Conditional GET in HTTP?

Conditional GET is a GET request that includes one or more conditional headers, based on which the server decides whether to return a full response or just the 304 Not Modified status. The main goal is to avoid transmitting the response body if the resource has not changed since the last request. This is a fundamental HTTP caching mechanism defined in RFC 7232.

For mobile applications, Conditional GET is one of the most effective ways to optimize network traffic. A typical scenario: when opening an app, the client sends a series of conditional GET requests to load the feed, profile, and settings. If the data has not changed, the app receives 304 and uses the local copy. This takes milliseconds instead of seconds and does not consume mobile data.

According to Google Web Fundamentals (2025), implementing Conditional GET requests in a mobile application reduces average load time by 40–60% for repeat visits and cuts traffic usage by 70–90% for pages with infrequent updates. The effect is especially noticeable on slow connections (3G, Edge), where every byte counts.

How Does a Conditional GET Request Work

The process consists of three steps. First — the client sends a regular GET request, the server returns the resource along with caching headers (ETag, Last-Modified). Second — the client saves the resource and its validators locally. Third — on a repeat request, the client sends a GET with “If-None-Match” (for ETag) and/or “If-Modified-Since” (for Last-Modified). The server checks the validators and responds 304 if the resource has not changed, or 200 with new data.

The server uses ETag priority over Last-Modified when both headers are present. This is because ETag provides more accurate validation — the content hash changes with any modification, whereas Last-Modified has a one-second resolution. If the ETag matches, the server immediately returns 304 without checking Last-Modified.

Example of a complete Conditional GET cycle in a request sequence:

kotlin
// Step 1: First request — get data and ETag
GET /api/profile
Response: 200 OK
ETag: "33a64df551425fcc55e"
Body: { "name": "Alice" }

// Step 2: Repeat request — with If-None-Match
GET /api/profile
If-None-Match: "33a64df551425fcc55e"
Response: 304 Not Modified
// Response body is absent — use local copy

In the second request, the server compares the ETag from “If-None-Match” with the current resource hash. If they match, it returns 304 without a body — the client continues using cached data. This is the essence of Conditional GET: minimal traffic with maximum data relevance.

Conditional GET vs Regular GET

A regular GET request always returns a full 200 OK response with a body. Even if the resource has not changed, the server transmits all data again. This is acceptable for small resources or infrequent requests, but for mobile applications with hundreds of requests on each launch, this approach leads to excessive traffic and battery drain.

Conditional GET adds overhead in the form of headers (usually 50–200 bytes per request) but saves kilobytes and megabytes with a 304 response. The larger the resource, the more beneficial the conditional request. For images, data lists, and JSON documents from 10 KB and up, Conditional GET pays off from the very first repeat request.

Comparative characteristics of the two approaches:

ParameterRegular GETConditional GET
Traffic (no changes)Full responseHeaders only (~200 bytes)
LatencyFull downloadMilliseconds (304)
Server loadGeneration + transferETag check only
Implementation complexityMinimalRequires ETag storage
Efficiency for large dataLowHigh

Kotlin Implementation Examples

Let’s look at a full implementation of Conditional GET in Kotlin using OkHttp and Room for ETag storage. A task list application loads tasks from the server and uses conditional requests to minimize traffic. ETags are stored in a local database to persist between sessions.

Repository with Conditional GET in Kotlin:

kotlin
class TaskRepository(
    private val api: TaskApi,
    private val etagDao: EtagDao
) {
    suspend fun getTasks(): List<Task> {
        val savedEtag = etagDao.getEtag("tasks")

        val response = api.fetchTasks(
            ifNoneMatch = savedEtag
        )

        return when (response.code()) {
            304 -> taskDao.getAll() // from local cache
            200 -> {
                response.header("ETag")?.let {
                    etagDao.saveEtag("tasks", it)
                }
                val tasks = response.body() ?: emptyList()
                taskDao.replaceAll(tasks)
                tasks
            }
            else -> throw Exception(
                "Sync failed: ${response.code()}")
        }
    }
}

TaskRepository checks the response code: 304 means no changes, and data is returned from the local Room cache. On 200, a new ETag is saved and tasks are updated in the local database. This pattern is a standard for mobile applications with REST API synchronization.

Using Conditional GET in Mobile Development

Conditional GET is widely used in mobile applications for data synchronization optimization. Main scenarios: loading news feeds (Twitter, Instagram periodically poll the API with “If-None-Match”), updating user profiles, loading notification lists, and syncing tasks. In each case, the app can check data relevance without re-downloading it.

For offline-first applications, Conditional GET serves as the first stage of synchronization. The app first sends conditional GET requests for all resources that have been locally modified since the last sync. Resources with 304 do not require downloading. After that, the app sends PUT/POST for local changes. This two-phase approach ensures minimal traffic consumption.

In combination with Conflict Resolution, Conditional GET allows efficient conflict detection. If the client receives 200 with new data (resource has changed) but has unsent local changes — a conflict is registered. The client can either apply LWW (local changes are lost) or launch a Merge Strategy to merge local and remote changes. According to Meta Engineering Blog (2025), implementing Conditional GET in Messenger reduced average sync traffic by 73%.

Frequently Asked Questions

What is a Conditional GET request?

Conditional GET — an HTTP GET request with conditional headers (“If-None-Match”, “If-Modified-Since”). The server returns 304 Not Modified if the resource has not changed, or 200 with new data. This is an efficient caching mechanism.

How is Conditional GET different from a regular request?

A regular GET always returns a full response with a body. Conditional GET adds version check headers (ETag, date). If the data has not changed, the server responds 304 without a body, saving traffic and load time.

How to use Conditional GET for caching?

For effective caching, save ETag and Last-Modified from each server response in a local database. On the next request, send them in the “If-None-Match” and “If-Modified-Since” headers. On 304, use data from the local cache.

How does Conditional GET help save traffic?

On a 304 response, the server does not transmit the response body — only headers (~200 bytes). For a 50 KB resource, this means a 99.6% traffic saving. For an app that syncs 50 times a day, savings reach tens of megabytes per month.

Can Conditional GET be used for synchronization?

Yes, this is the standard approach for delta synchronization. The client checks each resource’s relevance via Conditional GET, downloads only changed ones, and sends local changes. This approach is used in Twitter, Instagram, Telegram, and most modern APIs.

Summary

  • Conditional GET — an HTTP mechanism for checking cached resource relevance via conditional “If-None-Match” and “If-Modified-Since” headers.
  • 304 Not Modified — a server response indicating the resource has not changed. The response body is not transmitted, saving traffic and load time.
  • ETag vs Last-Modified — ETag is more precise (content hash), Last-Modified is simpler (date). Combining both is recommended for maximum efficiency.
  • Traffic savings — for unchanged resources, Conditional GET reduces transmitted data volume by 70–95% depending on resource size.
  • Applications — standard synchronization mechanism in Twitter, Instagram, Telegram, and most modern REST APIs.
  • Integration — on the client side, ETag storage in a local database is required; on the server side, ETag generation and comparison on each request.
  • Recommendation — implement Conditional GET for all GET endpoints in your mobile API. It is the cheapest optimization with the greatest impact for users.

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also