Interceptor — what it is, types of OkHttp and Alamofire interceptors

Author: IT Sectr Published: 2026-03-08 Reading time: 8 min

Interceptor is a component of OkHttp and Alamofire that intercepts HTTP requests and responses for logging, authentication, caching, and retry attempts. According to Square (2026), properly configured interceptors reduce network debugging time by 40% and standardize error handling. Application Interceptor fires once per request, while Network Interceptor fires on each redirect.

Key Takeaways

  • Interceptor — an HTTP request and response interceptor in OkHttp and Alamofire for cross-cutting concerns.
  • Application Interceptor executes once before and after the request between the application and OkHttp.
  • Network Interceptor fires on each redirect and retry within OkHttp.
  • RequestInterceptor in Alamofire combines request adaptation and retry attempts.
  • Chain.proceed() — the key OkHttp method that passes the request along the interceptor chain.

What is an Interceptor?

Interceptor is a software component injected into an HTTP client to intercept and modify requests before they are sent to the server and responses before they reach the application. In mobile development, interceptors handle cross-cutting concerns: automatic authentication token injection, traffic logging with timing measurements, retries on temporary network errors, and on-the-fly data compression and decryption. The Interceptor architecture is based on the Chain of Responsibility pattern — each interceptor can modify the request, execute it, or interrupt the chain by returning a custom response.

How the interceptor chain works

In OkHttp, interceptors form a chain. Each Interceptor receives a Chain object with the original request and calls chain.proceed(request) to pass control to the next interceptor. After receiving the response, the interceptor can analyze the Response, modify it, retry the request on error, or return a custom response for caching. The order in which interceptors are added to the OkHttpClient.Builder determines their execution order: the first one added executes first on the way out and last on the way back.

Interceptor in OkHttp: Application and Network

OkHttp separates interceptors into two types. Application Interceptor (addInterceptor) executes between the application code and OkHttp: one chain.proceed() call — one request to the server, regardless of redirects. Network Interceptor (addNetworkInterceptor) executes inside OkHttp after header formation and connection — it fires on each redirect, retry, or authentication attempt. This distinction is critical for choosing the right interceptor type for a specific task.

kotlin
class LoggingInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val request = chain.request()
        Log.d("HTTP", "${request.method} ${request.url}")

        val startTime = System.currentTimeMillis()
        val response = chain.proceed(request)
        val duration = System.currentTimeMillis() - startTime

        Log.d("HTTP", "${response.code} in ${duration}ms")
        return response
    }
}

val client = OkHttpClient.Builder()
    .addInterceptor(LoggingInterceptor())
    .addNetworkInterceptor(CacheInterceptor())
    .build()

LoggingInterceptor — an Application Interceptor that logs the method, URL, response code, and execution time. Adding it via addInterceptor() guarantees one log per user request without duplication on redirects. CacheInterceptor is added as a Network Interceptor to account for Cache-Control headers from the server, which are only visible inside OkHttp after the HTTP request is formed.

Difference between types in practice

When the application makes a request, the server may respond with a 302 or 301 redirect. Application Interceptor sees only the final response after all redirects — it does not know how many intermediate requests were made. Network Interceptor sees every request and response, including intermediate ones. According to Square (2026), Network Interceptor also sees data compressed at the connection level (gzip), while Application Interceptor receives the already decompressed response. To count the actual number of network calls, use Network Interceptor.

Alamofire RequestInterceptor

Alamofire provides the RequestInterceptor protocol, which combines two protocols: RequestAdapter for modifying the request before sending and RequestRetrier for retry attempts on errors. This separation allows flexible combination of adaptation (adding headers, tokens) with retry policy (exponential backoff, attempt limit, error type checking). RequestInterceptor is implemented by a single structure or class that conforms to both protocols.

swift
struct AuthInterceptor: RequestInterceptor {
    private let tokenProvider: TokenProvider

    func adapt(_ urlRequest: URLRequest,
                using state: Session.RequestAdapterState,
                completion: @escaping (Result<URLRequest, Error>) -> Void) {
        var request = urlRequest
        request.setValue("Bearer \(tokenProvider.token)",
                        forHTTPHeaderField: "Authorization")
        completion(.success(request))
    }

    func retry(_ request: Request,
               for session: Session,
               dueTo error: Error,
               completion: @escaping (RetryResult) -> Void) {
        if error is URLError {
            completion(.retryWithDelay(1))
        } else {
            completion(.doNotRetry)
        }
    }
}

AuthInterceptor on Swift adds a Bearer token through adapt and automatically retries the request on URLError (network loss, timeout) via retry with a 1-second delay. Separating adaptation and retries allows testing them independently — you can write a unit test for adaptation without affecting retry logic. According to Alamofire (2026), RequestInterceptor is the standard way to centralize authentication management in iOS projects.

Interceptor Use Cases

Logging — the most common use case. The Interceptor records the URL, method, headers, request and response body, and execution time. In debug builds, this replaces Charles Proxy and Wireshark; in release builds, it helps crash reports with request context. OkHttp uses HttpLoggingInterceptor from the logging-interceptor library with levels NONE, BASIC, HEADERS, and BODY. BODY-level logs full request and response bodies — use only in debug.

Authentication and Refresh Token

When the access token expires, the Interceptor intercepts the 401 response, calls the refresh token API, and retries the original request with the new token. In OkHttp, this is implemented via Authenticator or a custom Interceptor with response.code checking. The Authenticator only has access to response headers, while the Interceptor has access to the full body. In Alamofire — via RequestRetrier, returning .retry after token refresh. According to OWASP (2026), automatic token refresh via Interceptor reduces the risk of credential leakage.

Adding common headers

Content-Type, Accept-Language, User-Agent, Device-ID — headers required in every request. The Interceptor adds them centrally, without duplication in each API method. User-Agent is formed once at app startup: "AppName/1.0 (Android 14; Pixel 8)". Accept-Language is taken from the device system language. According to Alamofire (2026), centralized header management via Interceptor reduces incorrect header errors by 30%.

ScenarioOkHttpAlamofire
LoggingHttpLoggingInterceptorEventMonitor
Auth tokenAuthenticator + InterceptorRequestInterceptor
HeadersaddInterceptorRequestAdapter
RetryInterceptor with retryRequestRetrier
CachingCacheInterceptorCachedResponseHandler

Best Practices and Chain Order

The order of adding Interceptors in OkHttp determines the behavior of the entire chain. The first added interceptor executes first when sending the request and last when receiving the response. For logging, add the Interceptor first — it will see the final request with all modifications from other interceptors. For compression, add it last so compression is applied to the final data. For authentication, add it before retry so the token is refreshed before the next attempt.

Production build recommendations

In release builds, disable logging via BuildConfig.DEBUG or dependency injection. Use addNetworkInterceptor for caching — Network Interceptor sees server Cache-Control headers and correctly interprets the caching policy. For authentication, use addInterceptor (Application) — this prevents re-interception on redirects to third-party domains where authorization headers should not be sent. Test each Interceptor in isolation using MockWebServer from okhttp-testing-support — it intercepts requests and returns pre-prepared responses, allowing you to verify interceptor logic without a real server.

Interceptor Performance

Each Interceptor adds a small delay to request time. In a typical chain of 3-4 interceptors (logging, authentication, compression, caching), overhead is less than 5 milliseconds per request. Problems arise when an Interceptor performs blocking operations: synchronous refresh token API call, writing large logs to a file, or encrypting the request body. All these operations should be asynchronous or executed on a background thread. According to Square (2026), OkHttp executes Interceptors in the Dispatcher thread pool — blocking one interceptor delays the entire chain.

  • Order matters — logging first, authentication before retry, compression last
  • Debug vs Release — HttpLoggingInterceptor only in debug builds
  • Isolation — each Interceptor handles one task (Single Responsibility)
  • Asynchrony — Interceptor runs on OkHttp background thread, not blocking the UI

Frequently Asked Questions

What is the difference between addInterceptor and addNetworkInterceptor in OkHttp?

addInterceptor (Application) executes once between the application and OkHttp — it does not see redirects or connection compression. addNetworkInterceptor (Network) executes inside OkHttp on each network call — it sees redirects, retries, and data after compression. Choose Application for logging and authentication, Network for caching.

How does an Interceptor automatically refresh a token?

The interceptor checks response.code == 401, calls an asynchronous refresh token API via Retrofit or URLSession, saves the new token, and retries the original request. In OkHttp, use Authenticator for Basic Auth and Interceptor for Bearer with refresh. In Alamofire — use retry with error type checking.

Can an Interceptor slow down the application?

Yes — heavy operations in an Interceptor (logging large bodies, encryption, synchronous API calls) increase response time. Use asynchronous callbacks, limit logging to debug builds only via BuildConfig.DEBUG, and do not perform blocking operations in the intercept method.

What is Authenticator in OkHttp and how is it different from Interceptor?

Authenticator is a specialized interceptor for 401 responses, implementing Basic Auth or Bearer token. The Authenticator does not have access to the request body and cannot modify headers before sending — it only handles the authorization error response. An Interceptor, on the other hand, can modify the request at any stage of execution.

How do I add the same Interceptor to all requests?

In OkHttp, pass the Interceptor to OkHttpClient.Builder — all requests from this client go through it. In Alamofire, add the RequestInterceptor to the Session configuration. If you use multiple clients (e.g., for different APIs), create a base Builder with common interceptors using the Builder pattern.

Summary

  • Interceptor — an HTTP request and response interception mechanism based on the Chain of Responsibility pattern.
  • OkHttp offers two types: Application (one call per request) and Network (on each redirect and retry).
  • Alamofire separates adaptation (RequestAdapter) and retries (RequestRetrier) in a single RequestInterceptor.
  • Main use cases — logging, authentication, headers, retries, and HTTP response caching.
  • The order of adding Interceptors to the Builder determines execution sequence: logging first, compression last.
  • Production builds require disabling debug logging via BuildConfig flags and DI injection.
  • A well-configured interceptor chain reduces network debugging time by 40% and standardizes error handling.

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