HttpClient
A multiplatform asynchronous HTTP client that allows you to make requests, handle responses, and extend its functionality with plugins such as authentication, JSON serialization, and more.
Creating a client
To create a new client, you can call:
val client = HttpClient()
You can create as many clients as you need.
If you no longer need the client, please consider closing it to release resources:
client.close()
To learn more on how to create and configure an HttpClient, see Creating and configuring a client.
Making API Requests
For every HTTP method (GET, POST, PUT, etc.), there is a corresponding function:
val response: HttpResponse = client.get("https://ktor.io/")
val body = response.bodyAsText()
For more details, see Making HTTP requests.
Query Parameters
Add query parameters to your request using the parameter
function:
val response = client.get("https://google.com/search") {
url {
parameter("q", "REST API with Ktor")
}
}
For more information, refer to Passing request parameters.
Adding Headers
Include headers in your request using the headers
builder or the header
function:
val response = client.get("https://httpbin.org/bearer") {
headers {
append("Authorization", "Bearer your_token_here")
append("Accept", "application/json")
}
}
To learn more, see Adding headers to a request.
JSON Serialization
Add dependencies:
io.ktor:ktor-client-content-negotiation:3.+
io.ktor:ktor-serialization-kotlinx-json:3.+ Add Gradle plugin:
plugins {
kotlin("plugin.serialization")
}
Send and receive JSON data by installing the ContentNegotiation
plugin with kotlinx.serialization
:
val client = HttpClient {
install(ContentNegotiation) {
json()
}
}
@Serializable
data class MyRequestType(val someData: String)
@Serializable
data class MyResponseType(val someResponseData: String)
val response: MyResponseType = client.post("https://api.example.com/data") {
contentType(ContentType.Application.Json)
setBody(MyRequestType(someData = "value"))
}.body()
For Maven configuration and other details, see Serializing JSON data.
Submitting Forms
Submit form data using FormDataContent
or the submitForm
function:
// Using FormDataContent
val response = client.post("https://example.com/submit") {
setBody(FormDataContent(Parameters.build {
append("username", "user")
append("password", "pass")
}))
}
// Using submitForm
val response = client.submitForm(
url = "https://example.com/submit",
formParameters = Parameters.build {
append("username", "user")
append("password", "pass")
}
)
For more information, see Submitting form parameters.
Handling Authentication
Add dependency: io.ktor:ktor-client-auth:3.+
Use the Auth
plugin to handle various authentication schemes like Basic or Bearer token authentication:
val client = HttpClient {
install(Auth) {
bearer {
loadTokens {
BearerTokens(accessToken = "your_access_token", refreshToken = "your_refresh_token")
}
}
}
}
val response = client.get("https://api.example.com/protected")
For more details, refer to Client authentication.
Setting Timeouts and Retries
Configure timeouts and implement retry logic for your requests:
val client = HttpClient {
install(HttpTimeout) {
requestTimeoutMillis = 10000
connectTimeoutMillis = 5000
socketTimeoutMillis = 15000
}
}
For the request timeout:
client.get("") {
timeout {
requestTimeoutMillis = 1000
}
}
For more information, see the Timeout documentation.
Handling Cookies
Manage cookies automatically by installing the HttpCookies
plugin:
val client = HttpClient {
install(HttpCookies) {
storage = AcceptAllCookiesStorage()
}
}
// Accessing cookies
val cookies: List<Cookie> = client.cookies("https://example.com")
For more information, see the Cookies documentation.
Uploading Files
Upload files using multipart/form-data requests:
client.submitFormWithBinaryData(
url = "https://example.com/upload",
formData = formData {
append("description", "File upload example")
append("file", {
File("path/to/file.txt").readChannel()
})
}
)
For more details, see [Uploading data](https://ktor.io/docs/client-requests.html#upload_file).
# Using WebSockets
Communicate over WebSockets using the `webSocket` function:
```kotlin
client.webSocket("wss://echo.websocket.org") {
send(Frame.Text("Hello, WebSocket!"))
val frame = incoming.receive()
if (frame is Frame.Text) {
println("Received: ${frame.readText()}")
}
}
To learn more, see Client WebSockets.
Error Handling
Handle exceptions and HTTP error responses gracefully: val client = HttpClient { HttpResponseValidator { validateResponse { response -> val statusCode = response.status.value when (statusCode) { in 300..399 -> error("Redirects are not allowed") } } } }
For more information, see Error handling.
Configuring SSL/TLS
Customize SSL/TLS settings for secure connections is engine-specific. Please refer to the following page for the details: Client SSL/TLS.
Using Proxies
Route requests through an HTTP or SOCKS proxy:
val client = HttpClient() {
engine {
proxy = ProxyBuilder.http("http://proxy.example.com:8080")
// For a SOCKS proxy:
// proxy = ProxyBuilder.socks(host = "proxy.example.com", port = 1080)
}
}
For more details, see Using a proxy.
Streaming Data
Stream large data efficiently without loading it entirely into memory.
Stream request:
val response = client.post("https://example.com/upload") {
setBody(object: OutgoingContent.WriteChannelContent() {
override suspend fun writeTo(channel: ByteWriteChannel) {
repeat(1000) {
channel.writeString("Hello!")
}
}
})
}
Stream response:
client.prepareGet("https://example.com/largefile.zip").execute { response ->
val channel: ByteReadChannel = response.bodyAsChannel()
while (!channel.exhausted()) {
val chunk = channel.readBuffer()
// ...
}
}
Learn more at Streaming data.
Using SSE
Server-Sent Events (SSE) is a technology that allows a server to continuously push events to a client over an HTTP connection. It's particularly useful in cases where the server needs to send event-based updates without requiring the client to repeatedly poll the server.
Install the plugin:
val client = HttpClient(CIO) {
install(SSE)
}
client.sse(host = "0.0.0.0", port = 8080, path = "/events") {
while (true) {
for (event in incoming) {
println("Event from server:")
println(event)
}
}
}
For more information, see Using SSE.
Customizing a client with plugins
To extend out-of-the-box functionality, you can install plugins for a Ktor client:
val client = HttpClient {
install(ContentNegotiation) {
json()
}
}
There are many plugins available out of the box, and you can write your own. See Create custom client plugins to learn more.
Service Loader and Default Engine
On JVM, calling HttpClient()
without specifying an engine uses a service loader mechanism to determine the appropriate default engine. This can introduce a performance overhead, especially on slower devices, such as Android.
Performance Note: If you are targeting platforms where initialization speed is critical, consider explicitly specifying an engine to avoid the service loader lookup.
Example with manual engine specification:
val client = HttpClient(Apache) // Explicitly uses Apache engine, bypassing service loader
By directly setting the engine (e.g., Apache
, OkHttp
), you can optimize startup performance by preventing the default service loader mechanism.
A multiplatform asynchronous HTTP client that allows you to make requests, handle responses, and extend its functionality with plugins such as authentication, JSON serialization, and more.
Creating a client
To create a new client, you can call:
val client = HttpClient()
You can create as many clients as you need.
If you no longer need the client, please consider closing it to release resources:
client.close()
To learn more on how to create and configure an HttpClient see the tutorial page: Creating and configuring a client.
Making API Requests
For every HTTP method (GET, POST, PUT, etc.), there is a corresponding function:
val response: HttpResponse = client.get("https://ktor.io/")
val body = response.bodyAsText()
See Making HTTP requests for more details.
Query Parameters
Add query parameters to your request using the parameter
function:
val response = client.get("https://google.com/search") {
url {
parameter("q", "REST API with Ktor")
}
}
For more information, refer to Passing request parameters.
Adding Headers
Include headers in your request using the headers
builder or the header
function:
val response = client.get("https://httpbin.org/bearer") {
headers {
append("Authorization", "Bearer your_token_here")
append("Accept", "application/json")
}
}
Learn more at Adding headers to a request.
JSON Serialization
Add dependencies:
io.ktor:ktor-client-content-negotiation:3.+
io.ktor:ktor-serialization-kotlinx-json:3.+ Add Gradle plugin:
plugins {
kotlin("plugin.serialization")
}
Send and receive JSON data by installing the ContentNegotiation
plugin with kotlinx.serialization
:
val client = HttpClient {
install(ContentNegotiation) {
json()
}
}
@Serializable
data class MyRequestType(val someData: String)
@Serializable
data class MyResponseType(val someResponseData: String)
val response: MyResponseType = client.post("https://api.example.com/data") {
contentType(ContentType.Application.Json)
setBody(MyRequestType(someData = "value"))
}.body()
See Serializing JSON data for maven configuration and other details.
Submitting Forms
Submit form data using FormDataContent
or the submitForm
function:
// Using FormDataContent
val response = client.post("https://example.com/submit") {
setBody(FormDataContent(Parameters.build {
append("username", "user")
append("password", "pass")
}))
}
// Or using submitForm
val response = client.submitForm(
url = "https://example.com/submit",
formParameters = Parameters.build {
append("username", "user")
append("password", "pass")
}
)
More information is available at Submitting form parameters.
Handling Authentication
Add dependency: io.ktor:ktor-client-auth:3.+
Use the Auth
plugin to handle various authentication schemes like Basic or Bearer token authentication:
val client = HttpClient {
install(Auth) {
bearer {
loadTokens {
BearerTokens(accessToken = "your_access_token", refreshToken = "your_refresh_token")
}
}
}
}
val response = client.get("https://api.example.com/protected")
Refer to Client authentication for more details.
Setting Timeouts and Retries
Configure timeouts and implement retry logic for your requests:
val client = HttpClient {
install(HttpTimeout) {
requestTimeoutMillis = 10000
connectTimeoutMillis = 5000
socketTimeoutMillis = 15000
}
}
For the request timeout:
client.get("") {
timeout {
requestTimeoutMillis = 1000
}
}
See Timeout for more information.
Handling Cookies
Manage cookies automatically by installing the HttpCookies
plugin:
val client = HttpClient {
install(HttpCookies) {
storage = AcceptAllCookiesStorage()
}
}
// Accessing cookies
val cookies: List<Cookie> = client.cookies("https://example.com")
Learn more at Cookies.
Uploading Files
Upload files using multipart/form-data requests:
client.submitFormWithBinaryData(
url = "https://example.com/upload",
formData = formData {
append("description", "File upload example")
append("file", {
File("path/to/file.txt").readChannel()
})
}
)
See [Uploading data](https://ktor.io/docs/client-requests.html#upload_file) for details.
# Using WebSockets
Communicate over WebSockets using the `webSocket` function:
```kotlin
client.webSocket("wss://echo.websocket.org") {
send(Frame.Text("Hello, WebSocket!"))
val frame = incoming.receive()
if (frame is Frame.Text) {
println("Received: ${frame.readText()}")
}
}
Learn more at Client WebSockets.
Error Handling
Handle exceptions and HTTP error responses gracefully: val client = HttpClient { HttpResponseValidator { validateResponse { response -> val statusCode = response.status.value when (statusCode) { in 300..399 -> error("Redirects are not allowed") } } } }
See Error handling for more information.
Configuring SSL/TLS
Customize SSL/TLS settings for secure connections is engine-specific. Please refer to the following page for the details: Client SSL/TLS.
Using Proxies
Route requests through an HTTP or SOCKS proxy:
val client = HttpClient() {
engine {
proxy = ProxyBuilder.http("http://proxy.example.com:8080")
// For a SOCKS proxy:
// proxy = ProxyBuilder.socks(host = "proxy.example.com", port = 1080)
}
}
See Using a proxy for details.
Streaming Data
Stream large data efficiently without loading it entirely into memory.
Stream request:
val response = client.post("https://example.com/upload") {
setBody(object: OutgoingContent.WriteChannelContent() {
override suspend fun writeTo(channel: ByteWriteChannel) {
repeat(1000) {
channel.writeString("Hello!")
}
}
})
}
Stream response:
client.prepareGet("https://example.com/largefile.zip").execute { response ->
val channel: ByteReadChannel = response.bodyAsChannel()
while (!channel.exhausted()) {
val chunk = channel.readBuffer()
// ...
}
}
Learn more at Streaming data.
Using SSE
Server-Sent Events (SSE) is a technology that allows a server to continuously push events to a client over an HTTP connection. It's particularly useful in cases where the server needs to send event-based updates without requiring the client to repeatedly poll the server.
Install the plugin:
val client = HttpClient(CIO) {
install(SSE)
}
client.sse(host = "0.0.0.0", port = 8080, path = "/events") {
while (true) {
for (event in incoming) {
println("Event from server:")
println(event)
}
}
}
Visit Using SSE to learn more.
Customizing a client with plugins
To extend out-of-the-box functionality, you can install plugins for a Ktor client:
val client = HttpClient {
install(ContentNegotiation) {
json()
}
}
There are many plugins available out of the box, and you can write your own. See Create custom client plugins to learn more.
Service Loader and Default Engine
On JVM, calling HttpClient()
without specifying an engine uses a service loader mechanism to determine the appropriate default engine. This can introduce a performance overhead, especially on slower devices, such as Android.
Performance Note: If you are targeting platforms where initialization speed is critical, consider explicitly specifying an engine to avoid the service loader lookup.
Example with manual engine specification:
val client = HttpClient(Apache) // Explicitly uses Apache engine, bypassing service loader
By directly setting the engine (e.g., Apache
, OkHttp
), you can optimize startup performance by preventing the default service loader mechanism.
Constructs an asynchronous HttpClient using optional block for configuring this client.
The HttpClientEngine is selected from the dependencies. https://ktor.io/docs/http-client-engines.html
Constructs an asynchronous HttpClient using optional block for configuring this client.
The HttpClientEngine is selected from the dependencies. https://ktor.io/docs/http-client-engines.html