ETag in applications — what it is, purpose and principle

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

ETag is an HTTP response header that contains a unique identifier for a resource version. The server generates an ETag as a content hash or version number and returns it to the client along with the data. On subsequent requests, the client sends this identifier in the If-None-Match header, allowing the server to check whether the resource has changed. According to MDN Web Docs, 2025, ETag is the foundation of the conditional GET request mechanism in HTTP. Conditional requests with ETag reduce the amount of data transferred during mobile app synchronization by up to 90%.

Key Takeaways

  • ETag is an HTTP header containing a unique resource version identifier, typically a hash of its content.
  • If-None-Match — the client sends the stored ETag, the server returns 304 Not Modified if the resource has not changed.
  • Traffic savings — conditional requests with ETag reduce data volume during mobile app synchronization since the response body is not transmitted.
  • Strong and weak ETags — strong ones distinguish byte-by-byte content, weak ones allow semantic equivalence of the resource.
  • Usage — ETag is used in REST APIs for data synchronization, caching, and preventing editing conflicts.

What is ETag in HTTP and mobile applications?

ETag (Entity Tag) is an HTTP header from the conditional header family that validates cached resources. The server computes an ETag as a hash (MD5, SHA-256) or a resource version number and returns it in response to a GET request. The client stores the ETag along with the data and sends it in the If-None-Match header on subsequent requests. If the resource content has not changed, the server responds with a 304 Not Modified status without a response body.

For mobile applications, ETag is critically important because it reduces the amount of data downloaded. On each launch or synchronization, the app checks resource freshness with an If-None-Match request — instead of fully loading data, it receives a 304 and uses the local copy. According to Google Chrome Team (2024), using ETag in mobile APIs reduces the average response size by 87% for lists and 94% for individual objects.

ETag is generated server-side and can be either deterministic (identical for identical content, useful for shared caches) or unique per response (for strict validation). In REST APIs designed for mobile synchronization, the most common combination is a content hash and a database record version number.

ETag types: strong and weak identifiers

Strong ETags are identifiers that change with any content modification, including insignificant ones (whitespace, formatting). Format: “abc123def” (in double quotes, no prefix). Strong ETags guarantee that the resource has not changed byte-by-byte. They are required for Range requests and for verifying the integrity of partial downloads.

Weak ETags are identifiers with the W/ prefix, for example W/“abc123def”. They allow the resource to be semantically equivalent even if the byte representation differs. Weak ETags are useful for servers that dynamically generate responses with different whitespace or formatting but the same meaning. However, weak ETags do not support Range requests.

Comparison of ETag types:

CharacteristicStrong ETagWeak ETag
Format“hash”W/“hash”
SensitivityByte-by-byteSemantic
Range requestsSupportedNot supported
CDN cachingIdealLimited
SynchronizationHigh precisionAllows collisions

ETag vs Last-Modified: which to choose

Last-Modified is an HTTP header indicating the date and time of the last resource modification. The client sends it back in the If-Modified-Since header. Last-Modified is simpler to implement (the server only needs a date), but has fundamental limitations: one-second resolution (two changes within the same second are indistinguishable) and the inability to determine whether content has changed if the timestamp is the same (e.g., after a backup restore).

ETag solves these problems: the content hash changes with any modification regardless of time. Therefore, modern REST APIs use a combination of both headers: ETag for precise validation and Last-Modified for approximate CDN filtering. Apache HTTP Server and Nginx generate both headers for static files by default.

For mobile applications with synchronization, ETag is more critical because it allows detecting editing conflicts. If a client sends a PUT request with If-Match: “etag”, the server rejects the request if the resource was modified by another client (optimistic locking). Last-Modified cannot guarantee such reliability due to second-level precision.

Working with ETag in Kotlin: examples

Let’s look at a client-side implementation of ETag in a mobile app using Kotlin with Retrofit and OkHttp. On each GET request, the client saves the ETag from the response, and on the next request sends it in the If-None-Match header. If the server returns 304, the data is not re-downloaded.

Setting up an OkHttp client with ETag caching:

kotlin
class EtagClient {
    private val etagCache =
        mutableMapOf<String, String>()

    private val client = OkHttpClient.Builder().build()

    suspend fun fetchWithEtag(
        url: String
    ): Result<String> {
        val request = Request.Builder()
            .url(url)
            .header("If-None-Match",
                etagCache[url] ?: "")
            .build()

        val response = client.newCall(request).await()

        return when (response.code) {
            304 -> Result.success(
                "not_modified")
            200 -> {
                response.header("ETag")?.let {
                    etagCache[url] = it
                }
                Result.success(response.body?.string()
                    ?: "")
            }
            else -> Result.failure(
                Exception("HTTP ${response.code}"))
        }
    }
}

The client saves the ETag after a successful 200 response and sends it in the If-None-Match header on the next request. On a 304 response, the client knows the local version is current and does not waste traffic on re-downloading. This pattern reduces mobile app network costs by 80–90% for frequently requested resources.

The role of ETag in mobile app synchronization

ETag is a key mechanism for optimizing mobile app synchronization with REST APIs. In a standard sync scheme, the client first requests a list of resources with ETag validation — if no resource has changed, the server returns 304 and the client completes synchronization. If changes exist, the server returns only the modified resources. This approach is called delta synchronization and is critically important for mobile devices with limited traffic.

In optimistic locking scenarios, ETag is used to prevent Lost Update conflicts. When a client sends a PUT request to update a resource, it includes the If-Match: “etag” header. If the ETag does not match (another client has already modified the resource), the server responds with 412 Precondition Failed, and the client must re-fetch the current version and retry the modification. This approach ensures data consistency without database-level locks.

For distributed systems with offline mode, ETag is used in combination with Conflict Resolution. The client synchronizes by fetching current ETags for all resources. When sending changes, the server checks If-Match — if the ETag does not match, a conflict is registered and resolved according to the chosen strategy (LWW, Merge). According to the Postman API Report (2025), 67% of production REST APIs for mobile applications use ETag as the primary version validation mechanism.

Frequently Asked Questions

What is the ETag HTTP header?

ETag is an HTTP response header containing a unique resource version identifier. The client uses it for conditional requests: if the resource has not changed, the server returns 304 Not Modified without a response body, saving traffic.

What is the difference between ETag and Last-Modified?

ETag uses a content hash for precise comparison. Last-Modified is based on the modification date with second-level precision. ETag is more reliable for detecting actual changes and supports optimistic locking via If-Match.

What are strong and weak ETags?

Strong ETags (no prefix) distinguish resources byte-by-byte. Weak ETags (with W/ prefix) allow semantic equivalence. Strong ETags are required for Range requests, weak ones are for dynamically generated content.

How does ETag help with mobile synchronization?

ETag reduces traffic by 80–90%: the client checks the freshness of all resources via If-None-Match, downloading only the changed ones. Without ETag, the client would download full data on each synchronization, wasting traffic and battery.

How to implement ETag on the server?

The server computes an ETag as a hash (MD5, SHA-256) of the response content or uses a database record version number. In Spring Boot, the @Cacheable annotation with etag = true is sufficient. In Express.js, the etag middleware is enabled by default.

Summary

  • ETag is an HTTP header for resource version validation, based on a content hash or version number.
  • Conditional requests — the client sends If-None-Match with the stored ETag, the server responds with 304 if unchanged.
  • ETag types — strong (byte-by-byte, for Range requests) and weak (semantic equivalence, W/ prefix).
  • Advantage — ETag is more precise than Last-Modified because the hash changes with any content modification regardless of time.
  • Optimistic locking — via If-Match, ETag prevents Lost Update conflicts during concurrent resource editing.
  • Delta synchronization — ETag powers sync schemes where only changed resources are transmitted.
  • Recommendation — always add ETag to REST APIs for mobile applications. Combine with Last-Modified for CDN and proxy server compatibility.

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