---
title: "Capture TLS Traffic | Speedscale Docs"
description: "Capture TLS traffic in Kubernetes with the Speedscale eBPF collector, without adding certificates or configuring a proxy."
canonical: "https://docs.speedscale.com/guides/tls/"
---

[Documentation index](https://docs.speedscale.com/guides/llms.txt) | [Markdown](https://docs.speedscale.com/guides/tls/index.md) | [Canonical page](https://docs.speedscale.com/guides/tls/)

# Capture TLS Traffic

<a id="prerequisites"></a>

## Prerequisites

1.  [Install the Operator](https://docs.speedscale.com/getting-started/quick-start/).
2.  [Enable the eBPF collector](https://docs.speedscale.com/reference/ebpf-traffic-collection/#installation) and target your workload.
3.  Confirm that your language and TLS library are listed under [TLS Traffic Visibility](https://docs.speedscale.com/reference/ebpf-traffic-collection/#tls-traffic-visibility).

<a id="our-app"></a>

## Our app

For this guide, we are using an app called `bq-app` that has an endpoint `/name/{state}` and makes calls out to Google's BigQuery on every inbound request.

<a id="viewing-traffic"></a>

## Viewing traffic

![Traffic](https://docs.speedscale.com/assets/images/unrecognized-cd7a28631adb9508d0ebdf48f7bf19a2.png)

In the traffic viewer for our service, we can see individual requests and their headers and bodies. If a request is marked as TLS, Speedscale observed the connection but could not read the plaintext payload.

<a id="enable-tls-capture"></a>

## Enable TLS capture

The eBPF collector reads plaintext at supported TLS library boundaries. It does not require a Speedscale certificate, a proxy, or the `sidecar.speedscale.com/tls-out` annotation.

Enable capture for the deployment:

```bash
kubectl annotate deployment bq-app -n YOUR_NAMESPACE \
  capture.speedscale.com/enabled="true" --overwrite
```

Java workloads also require the Operator-managed JVMTI agent. Enable it before restarting the workload:

```bash
kubectl annotate deployment bq-app -n YOUR_NAMESPACE \
  capture.speedscale.com/java-agent="true" --overwrite
```

The Java agent changes the pod template so it can load inside the JVM. See [Java eBPF capture](https://docs.speedscale.com/reference/languages/java/#ebpf-java-agent) for details.

Restart long-lived workloads after enabling capture so the collector sees new TLS connections from the beginning:

```bash
kubectl rollout restart deployment bq-app -n YOUR_NAMESPACE
```

![Decoded](https://docs.speedscale.com/assets/images/decoded-6c237b2e7e1f8eabfa1fd103c97dc97e.png)

The previously opaque requests are now decoded. In this example, the application makes one POST request for the BigQuery query and two GET requests to paginate through the results.

<a id="if-traffic-remains-encrypted"></a>

## If traffic remains encrypted

Check the collector requirements before changing your application:

*   Go applications require Go 1.18 or newer and an unstripped binary built without `-ldflags="-s"`.
*   OpenSSL capture requires OpenSSL 3.x. BoringSSL, LibreSSL, and older OpenSSL releases are not supported by the eBPF TLS probes.
*   Rust applications using rustls require `nettap` v0.1.77 or newer and an unstripped Linux ELF binary that retains the rustls probe symbols. Rust applications using OpenSSL follow the OpenSSL 3.x requirement.
*   JVM applications written in Java or Kotlin use the Speedscale JVMTI agent, which the Operator manages with the eBPF collector.
*   Connections established before the probes attach can remain opaque until the application opens a new connection.

See [eBPF limitations](https://docs.speedscale.com/reference/ebpf-traffic-collection/#limitations) for the complete list. Existing sidecar deployments can continue to use the legacy [sidecar TLS configuration](https://docs.speedscale.com/getting-started/installation/sidecar/tls/).
