HTTP Client in Kotlin: Making Requests Correctly from A to Z
Modern development in Kotlin is unthinkable without network interaction. Whether it's an Android application, a server-side solution on Ktor, or a desktop application — HTTP requests remain the primary way to exchange data. In this article, we will break down how to properly organize an HTTP client in Kotlin, review popular libraries, and best practices.
Why Kotlin is Ideal for HTTP Requests?
Kotlin offers modern syntax, null safety, and full compatibility with the Java ecosystem. Thanks to coroutines and streaming APIs, working with the network becomes clean and asynchronous. Key advantages:
- Coroutines — lightweight threads for asynchronous operations without blocking
- Type-safe builders — convenient construction of HTTP requests
- Sealed classes — elegant handling of response states
- Extension functions — extending library functionality
Choosing an HTTP Client for Kotlin
Today, three libraries dominate the Kotlin ecosystem: OkHttp, Ktor Client, and Retrofit. Let's look at each with code examples.
1. OkHttp — A Time-Tested Choice
OkHttp from Square is the most popular HTTP client for JVM. It is efficient, supports HTTP/2, automatic compression, and caching.
// build.gradle.ktsimplementation("com.squareup.okhttp3:okhttp:4.12.0")
// Example GET request with OkHttpimport okhttp3.OkHttpClientimport okhttp3.Requestimport kotlinx.coroutines.Dispatchersimport kotlinx.coroutines.withContext
class OkHttpExample { private val client = OkHttpClient.Builder() .connectTimeout(30, java.util.concurrent.TimeUnit.SECONDS) .readTimeout(30, java.util.concurrent.TimeUnit.SECONDS) .build()
suspend fun fetchData(url: String): String = withContext(Dispatchers.IO) { val request = Request.Builder() .url(url) .header("Accept", "application/json") .build()
client.newCall(request).execute().use { response -> if (!response.isSuccessful) { throw RuntimeException("Error: ${response.code}") } response.body?.string() ?: throw RuntimeException("Empty response") } }}2. Ktor Client — A Native Choice for Kotlin
Ktor Client is part of the JetBrains ecosystem, fully written in Kotlin with multiplatform support. Ideal for Ktor servers and Android/iOS projects.
// build.gradle.ktsimplementation("io.ktor:ktor-client-core:2.3.7")implementation("io.ktor:ktor-client-cio:2.3.7")implementation("io.ktor:ktor-client-content-negotiation:2.3.7")implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.7")
import io.ktor.client.*import io.ktor.client.call.*import io.ktor.client.engine.cio.*import io.ktor.client.plugins.contentnegotiation.*import io.ktor.client.request.*import io.ktor.client.statement.*import io.ktor.serialization.kotlinx.json.*import kotlinx.serialization.Serializable
@Serializabledata class Post(val userId: Int, val id: Int, val title: String, val body: String)
class KtorExample { private val client = HttpClient(CIO) { install(ContentNegotiation) { json(Json { ignoreUnknownKeys = true isLenient = true }) } engine { requestTimeout = 30_000 } }
suspend fun getPost(id: Int): Post { val response: HttpResponse = client.get("https://jsonplaceholder.typicode.com/posts/$id") return response.body() }
suspend fun createPost(post: Post): Post { val response: HttpResponse = client.post("https://jsonplaceholder.typicode.com/posts") { setBody(post)