---
title: "Ktor Client Integration"
description: "Learn how to capture tracing information when using Ktor Client."
url: https://docs.sentry.io/platforms/java/tracing/instrumentation/ktor-client/
---

# Ktor Client Integration | Sentry for Java

To be able to capture transactions, you'll need to first [set up tracing](https://docs.sentry.io/platforms/java/tracing.md).

The `sentry-ktor-client` library provides [Ktor Client](https://ktor.io/) support for Sentry via the Sentry Ktor Client Plugin.

On this page, we get you up and running with Sentry's Ktor Client Integration. The integration supports:

* Adding breadcrumbs for each HTTP request.
* Capturing spans for each HTTP Request, with support for distributed tracing. The span will be created as a child of the current span bound to the scope (if any).
* Capturing certain request failures as errors in Sentry.

The Sentry Ktor Client integration supports Ktor Client version `3.x`.

If you're using Ktor Client with OKHttp as the engine, and you're already using the [Sentry OkHttp integration](https://docs.sentry.io/platforms/java/tracing/instrumentation/okhttp.md), you should avoid using this integration, otherwise the SDK will produce duplicate data, instrumenting each HTTP request twice. Use the [Sentry OkHttp integration](https://docs.sentry.io/platforms/java/tracing/instrumentation/okhttp.md) instead, as it provides more detailed information about HTTP request.

## [Install](https://docs.sentry.io/platforms/java/tracing/instrumentation/ktor-client.md#install)

To install the integration:

```groovy
implementation 'io.sentry:sentry-ktor-client:8.37.1'
```

## [Configure](https://docs.sentry.io/platforms/java/tracing/instrumentation/ktor-client.md#configure)

Create the Ktor HTTP Client with your preferred engine, and install the Sentry Ktor Client Plugin:

```kotlin
import io.ktor.client.*
import io.ktor.client.engine.java.*
import io.sentry.ktorClient.SentryKtorClientPlugin

val ktorClient = HttpClient(Java) {
    install(SentryKtorClientPlugin)
}
```

## [Verify](https://docs.sentry.io/platforms/java/tracing/instrumentation/ktor-client.md#verify)

This snippet includes an HTTP Request and captures an intentional message, so you can verify that everything is working as soon as you set it up:

```kotlin
import io.ktor.client.*
import io.ktor.client.engine.java.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.sentry.ktorClient.SentryKtorClientPlugin
import io.sentry.Sentry

suspend fun run(url: String): String? {
  val ktorClient = HttpClient(Java) {
    install(SentryKtorClientPlugin)
  }

  val response = ktorClient.get(url)
  val bodyStr = response.bodyAsText()

  Sentry.captureMessage("The Message $bodyStr")

  return bodyStr
}
```

To view and resolve the recorded message, log into [sentry.io](https://sentry.io) and open your project. Clicking on the error's title will open a page where you can see detailed information and mark it as resolved.

## [Customize the Recorded Span](https://docs.sentry.io/platforms/java/tracing/instrumentation/ktor-client.md#customize-the-recorded-span)

The captured span can be customized or dropped with a `BeforeSpanCallback`:

```kotlin
import io.ktor.client.*
import io.ktor.client.engine.java.*
import io.ktor.client.request.*
import io.ktor.http.*
import io.sentry.ISpan
import io.sentry.ktorClient.SentryKtorClientPlugin

val ktorClient = HttpClient(Java) {
  install(SentryKtorClientPlugin) {
    beforeSpan = { span, request ->
      // Drop spans for admin requests
      if (request.url.toString().contains("/admin")) {
        null
      } else {
        span
      }
    }
  }
}
```

## [HTTP Client Errors](https://docs.sentry.io/platforms/java/tracing/instrumentation/ktor-client.md#http-client-errors)

This feature automatically captures HTTP client errors (like bad response codes) as error events and reports them to Sentry. The error event will contain the `request` and `response` data, including the `url`, `status_code`, and so on.

HTTP client error capturing is enabled by default. The SDK captures HTTP client errors with a response code between `500` and `599`, but you can change this behavior by configuring the plugin:

```kotlin
import io.ktor.client.*
import io.ktor.client.engine.java.*
import io.sentry.HttpStatusCodeRange
import io.sentry.ktorClient.SentryKtorClientPlugin

val ktorClient = HttpClient(Java) {
  install(SentryKtorClientPlugin) {
    captureFailedRequests = true
    failedRequestStatusCodes = listOf(HttpStatusCodeRange(400, 599))
  }
}
```

HTTP client errors from every target (`.*` regular expression) are automatically captured, but you can change this behavior by setting the `failedRequestTargets` option with either a regular expression or a plain `String`. A plain string must contain at least one of the items from the list. Plain strings don't have to be full matches, meaning the URL of a request is matched when it contains a string provided through the option.

```kotlin
import io.ktor.client.*
import io.ktor.client.engine.java.*
import io.sentry.ktorClient.SentryKtorClientPlugin

val ktorClient = HttpClient(Java) {
  install(SentryKtorClientPlugin) {
    captureFailedRequests = true
    failedRequestTargets = listOf("myapi.com")
  }
}
```

By default, error events won't contain any PII data, such as `Headers` and `Cookies`, but you can change this behavior by setting the `sendDefaultPii` option to `true`:

```kotlin
Sentry.init { options ->
  options.isSendDefaultPii = true
}
```

Those events are searchable and you can set alerts on them if you use the `http.url` and `http.status_code` properties. Learn more in our full [Searchable Properties](https://docs.sentry.io/concepts/search/searchable-properties.md) documentation.

### [Customize or Drop the Error Event](https://docs.sentry.io/platforms/java/tracing/instrumentation/ktor-client.md#customize-or-drop-the-error-event)

The captured error event can be customized or dropped with a `BeforeSendCallback`:

```kotlin
import io.sentry.Sentry
import io.sentry.SentryOptions.BeforeSendCallback
import io.sentry.TypeCheckHint.KTOR_CLIENT_REQUEST
import io.sentry.TypeCheckHint.KTOR_CLIENT_RESPONSE
import io.ktor.client.request.*
import io.ktor.client.statement.*

Sentry.init { options ->
  // Add a callback that will be used before the event is sent to Sentry.
  // With this callback, you can modify the event or, when returning null, also discard the event.
  options.beforeSend = BeforeSendCallback { event, hint ->
    val request = hint.getAs(KTOR_CLIENT_REQUEST, HttpRequest::class.java)
    val response = hint.getAs(KTOR_CLIENT_RESPONSE, HttpResponse::class.java)

    // customize or drop the event
    event
  }
}
```
