---
title: "Transports"
description: "Learn more about customizing how the Sentry SDK sends data to Sentry."
url: https://docs.sentry.io/platforms/native/configuration/transports/
---

# Transports for Native

The Native SDK uses *Transports* to send event payloads to Sentry. The default transport depends on the target platform:

* **Windows**: WinHTTP
* **Linux**: Curl
* **macOS**: Curl

## [Custom Transports](https://docs.sentry.io/platforms/native/configuration/transports.md#custom-transports)

To specify a custom transport, use the `sentry_options_set_transport` function and supply a transport that implements the `sentry_transport_t` interface.

```c
#include <sentry.h>

void custom_transport(sentry_envelope_t *envelope, void *state) {
  /*
   * Send the event here. If the transport requires state, such as an HTTP
   * client object or request queue, it can be specified in the `state`
   * parameter when configuring the transport. It will be passed as second
   * argument to this function.
   * The transport takes ownership of the `envelope`, and must free it once it
   * is done.
   */
  sentry_envelope_free(envelope);
}

int main(void) {
  void *transport_state = 0;

  sentry_options_t *options = sentry_options_new();
  sentry_transport_t *transport = sentry_transport_new(custom_transport);
  sentry_transport_set_state(transport, transport_state);

  sentry_options_set_transport(options, transport);
  sentry_init(options);

  /* ... */
}
```

The transport is invoked in the same thread as the call to `sentry_capture_event`. Consider to offload network communication to a background thread or thread pool to avoid blocking execution.

## [Using a Proxy](https://docs.sentry.io/platforms/native/configuration/transports.md#using-a-proxy)

The Native SDK allows the configuration of an `HTTP` (`CONNECT`) or `SOCKS5` proxy through which requests can be tunneled to our backend. It can be configured manually via the following option interface:

```c
sentry_options_t *options = sentry_options_new();
sentry_options_set_proxy(options, "http://my.proxy:8080");
sentry_init(options);

/* ... */
```

The same function can also be used for the `SOCKS5` proxy:

```c
sentry_options_t *options = sentry_options_new();
sentry_options_set_proxy(options, "socks5://my.proxy:1080");
sentry_init(options);

/* ... */
```

### [Proxy behavior](https://docs.sentry.io/platforms/native/configuration/transports.md#proxy-behavior)

We support `HTTP` proxies on all platforms, and `SOCKS5` proxies on Linux and macOS. On Windows, `https` proxy servers are not supported by the default transport (WinHTTP). The proxy may also contain authentication (`"http://user:password@my.proxy:8080"`) or be written in IPv6 format (`"http://[::1]:8080"`).

The SDK will always automatically configure the HTTP proxy if a corresponding environment variable is set. Depending on the [DSN](https://docs.sentry.io/concepts/key-terms/dsn-explainer.md) protocol, the matching `http(s)_proxy` environment variable is read. So for a usual Sentry-hosted `DSN`, you must set the `https_proxy` variable .

If you don't want the SDK to configure the HTTP proxy from the environment variables automatically, you can set the proxy option to an empty string value:

```c
sentry_options_t *options = sentry_options_new();
sentry_options_set_proxy(options, "");
sentry_init(options);

/* ... */
```

## [Retrying Failed Uploads](https://docs.sentry.io/platforms/native/configuration/transports.md#retrying-failed-uploads)

To enable retrying failed uploads, use the `sentry_options_set_http_retry` function:

```c
sentry_options_t *options = sentry_options_new();
sentry_options_set_http_retry(options, 1);
sentry_init(options);

/* ... */
```

With HTTP retry enabled, envelopes that fail to upload because of a network failure, such as a connection error or a timeout, are written to the `cache/` subdirectory of the [database path](https://docs.sentry.io/platforms/native/configuration/options.md#database_path) and sent again later. The SDK doesn't retry HTTP error responses, including `5xx` status codes. HTTP retry applies to the HTTP transport, including HTTP clients plugged in with `sentry_http_transport_new`, but not to custom function transports created with `sentry_transport_new`.

The SDK retries each envelope up to 6 times with exponential backoff, starting at 15 minutes and doubling up to 8 hours. It doesn't detect network connectivity, but checks for pending envelopes every 15 minutes while it runs. On the next start, the SDK sends any envelopes still pending from the previous run. When the retries run out, the SDK discards the envelope, or keeps it in the cache if [offline caching](https://docs.sentry.io/platforms/native/configuration/transports.md#offline-caching) is enabled.

The `crashpad` backend's handler process has its own internal HTTP retry mechanism, which follows the same schedule but isn't controlled by the SDK transport's `http_retry` option.

## [Offline Caching](https://docs.sentry.io/platforms/native/configuration/transports.md#offline-caching)

To keep envelopes on disk, use the `sentry_options_set_cache_keep` function with one of the following modes:

* `SENTRY_CACHE_KEEP_NONE`: The SDK doesn't keep envelopes. This is the default.
* `SENTRY_CACHE_KEEP_OFFLINE`: The SDK keeps envelopes that it can't upload. This includes envelopes that failed because of a network failure, envelopes whose retries ran out, and envelopes captured before user consent is given.
* `SENTRY_CACHE_KEEP_ALWAYS`: The SDK keeps every envelope, regardless of the upload result.

The SDK writes kept envelopes to the `cache/` subdirectory of the database path as `<uuid>.envelope` files, and stores minidumps next to them as `.dmp` files. To send envelopes again after a network failure, enable [HTTP retry](https://docs.sentry.io/platforms/native/configuration/transports.md#retrying-failed-uploads) as well. Like HTTP retry, offline caching applies to the HTTP transport only.

On startup, the SDK removes the oldest entries from the cache, including pending retries, until the cache is within the following limits:

* `cache_max_items`: The maximum number of entries. Defaults to `30`.
* `cache_max_size`: The maximum size in bytes. Defaults to `0` (no limit).
* `cache_max_age`: The maximum age in seconds. Defaults to `0` (no limit).

The SDK reports entries removed because of `cache_max_items` or `cache_max_size` as `cache_overflow` in [client reports](https://docs.sentry.io/platforms/native/configuration/options.md#send_client_reports).

By default, the **`crashpad` backend** keeps its historical cleanup limits for backwards compatibility: `sentry_init` removes crash reports older than 2 days and the oldest reports beyond 8 MB in total. When offline caching is explicitly enabled, the `cache_max_*` options replace these limits.

```c
sentry_options_t *options = sentry_options_new();
sentry_options_set_http_retry(options, 1);
sentry_options_set_cache_keep(options, SENTRY_CACHE_KEEP_OFFLINE);
sentry_options_set_cache_max_items(options, 100);
sentry_options_set_cache_max_size(options, 10 * 1024 * 1024); /* 10 MB */
sentry_options_set_cache_max_age(options, 7 * 24 * 60 * 60); /* 7 days */
sentry_init(options);

/* ... */
```

When [`require_user_consent`](https://docs.sentry.io/platforms/native/configuration/options.md#require_user_consent) is enabled together with offline caching or HTTP retry, the SDK writes envelopes captured before consent is given to the cache instead of discarding them. With HTTP retry, the SDK sends them once the application gives consent with `sentry_user_consent_give`.
