HTTP Client in Kotlin: Making Requests Properly from A to Z

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

HTTP Client in Kotlin: Making Requests Properly from A to Z

\n

Modern development in Kotlin is unthinkable without interaction with remote servers. Whether it's a mobile application on Android or a server-side solution on Ktor — HTTP requests are the foundation of data exchange. In this article, we will cover how to create HTTP clients in Kotlin using best practices, popular libraries, and a modern approach with coroutines. You will learn how to make GET and POST requests, handle errors, work with JSON, and build a reliable network layer architecture.

\n\n

Why Kotlin is Ideal for HTTP Clients?

\n

Kotlin offers concise syntax, null safety, and full compatibility with the Java ecosystem. Thanks to coroutines, asynchronous requests become intuitive, without cumbersome callbacks. You can write sequential code that executes asynchronously — this significantly simplifies reading and debugging. Additionally, Kotlin is actively used in Android development, where network requests are a daily task.

\n\n

Main Libraries for HTTP in Kotlin

\n

Currently, the three most popular approaches are:

\n
    \n
  • Ktor Client — a multiplatform client from JetBrains. Supports JVM, Android, iOS, JS, and Native. Ideal for projects requiring a single codebase.
  • \n
  • OkHttp + Retrofit — the classic stack for Android/JVM. OkHttp handles low-level network operations, while Retrofit generates typed interfaces.
  • \n
  • Fuel — a lightweight library with a functional approach. Suitable for small projects.
  • \n
\n

In this article, we will focus on Ktor and OkHttp, as they cover 90% of scenarios.

\n\n

Project Setup and First Requests

\n

First, let's add dependencies. If you are using Gradle (Kotlin DSL), add Ktor Client:

\n
dependencies {\n    implementation("io.ktor:ktor-client-core:2.3.7")\n    implementation("io.ktor:ktor-client-cio:2.3.7") // CIO engine\n    implementation("io.ktor:ktor-client-content-negotiation:2.3.7")\n    implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.7")\n}
\n

For OkHttp, the dependencies will be:

\n
dependencies {\n    implementation("com.squareup.okhttp3:okhttp:4.12.0")\n    implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")\n    implementation("com.google.code.gson:gson:2.10.1")\n}
\n\n

GET Request with Ktor Client

\n

Let's create a simple client and make a GET request to a public API:

\n
import io.ktor.client.*\nimport io.ktor.client.request.*\nimport io.ktor.client.statement.*\n\nsuspend fun fetchData(): String {\n    val client = HttpClient()\n    val response: HttpResponse = client.get("https://jsonplaceholder.typicode.com/posts/1")\n    val body = response.bodyAsText()\n    client.close()\n    return body\n}\n\n// Usage in a coroutine\nfun main() = runBlocking {\n    println(fetchData())\n}
\n

Note: suspend is a Kotlin keyword for suspendable functions. This allows executing requests without blocking the thread.

\n\n

GET Request with OkHttp

\n

A similar example with OkHttp looks like this:

\n
import okhttp3.OkHttpClient\nimport okhttp3.Request\n\nfun fetchDataSync(): String {\n    val client = OkHttpClient()\n    val request = Request.Builder()\n        .url("https://jsonplaceholder.typicode.com/posts/1")\n        .build()\n    client.newCall(request).execute().use { response ->\n        return response.body?.string() ?: "Error"\n    }\n}\n\n// Call in a regular thread (blocking)\nfun main() {\n    println(fetchDataSync())\n}
\n

OkHttp is synchronous by default, but it can be easily adapted for coroutines using suspendCancellableCoroutine.

\n\n

POST Requests and Working with JSON

\n

Sending data is the second most important operation. Let's look at how to send JS

Blogs

Book Recommendations