🎉 We just launched long anticipated residential proxies & pay-per-GB!
Pay once, switch between multiple proxy providers.
50% discount for a limited time. See more →
Documentation menu

Cache certificate setup

Choose a cache-mode TLS option#

No _cache- password suffix? Change nothing. Ordinary proxy mode keeps end-to-end TLS and requires no certificate installation or client TLS changes for the plaintext http:// proxy endpoint. The https:// proxy endpoint is the one exception: its hub certificate chains to this same root, so trust it for the proxy connection as described in HTTP vs HTTPS proxy endpoint. That trust alone never enables cache mode.

With cache mode active, choose one:

Option Certificate verification Best for
Trust the Litport root (Recommended) On Ongoing cache clients and dedicated automation profiles
Skip certificate verification Off Isolated public-data automation where you accept the security tradeoff

Skipping verification means the client cannot authenticate target certificates. Never use that option for logins, payments, private APIs, cookies, or sensitive traffic.

The proxy URL may begin with http:// because it identifies the HTTP proxy endpoint. The target still remains https://example.com/...; proxy endpoint scheme and target scheme are different.

Skip verification for isolated public-data automation#

Use this option only in a dedicated cache client that fetches public static data. It disables the client's target-certificate authentication; it does not make private traffic safe to intercept. Keep the proxy credentials in a secret store and remove the cache suffix when the isolated workload ends.

curl#

curl --insecure --proxy 'http://hub-us-7.litport.net:PORT' \
  --proxy-user 'USER:PASSWORD_cache-scripts' \
  'https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js'

Python Requests#

import requests

requests.get(
    'https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js',
    proxies={'https': 'http://USER:[email protected]:PORT'},
    verify=False,
    timeout=30,
)

Node#

NODE_TLS_REJECT_UNAUTHORIZED=0 node scraper.mjs

Configure the HTTP proxy in that isolated Node process. This environment setting disables certificate verification for that process; do not set it for a general-purpose service.

Browser automation#

import { chromium } from 'playwright'

const browser = await chromium.launch({ proxy: {
  server: 'http://hub-us-7.litport.net:PORT',
  username: 'USER',
  password: 'PASSWORD_cache-scripts',
}})
const context = await browser.newContext({ ignoreHTTPSErrors: true })
await (await context.newPage()).goto('https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js')

Use a dedicated browser profile for this workload. Do not browse signed-in or sensitive sites with it.

Go#

proxyURL, err := url.Parse("http://USER:[email protected]:PORT")
if err != nil { log.Fatal(err) }
client := &http.Client{Transport: &http.Transport{
  Proxy: http.ProxyURL(proxyURL),
  TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // public-data-only isolated client
}}
response, err := client.Get("https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js")

Two verified TLS legs#

Cache mode terminates the client-facing TLS connection at the selected Litport hub so it can read an eligible response and serve a later local copy. The client verifies the issued target certificate against the Litport cache root. Separately, the hub verifies the real origin certificate and hostname before reading the origin response. Keep verification enabled at both trust boundaries.

Your clientTrusts the public Litport cache root
Litport-issued certificate for the targetTLS leg 1
Litport hubCan read this cache-mode request and response
Public certificate and hostname verifiedTLS leg 2
HTTPS originReached through the selected upstream
The client verifies the Litport-issued target certificate on TLS leg 1. The hub separately verifies the public origin certificate and hostname on TLS leg 2.

An HTTP target has no authenticated origin identity and stays on the ordinary proxy path. Use an HTTPS target for cache mode.

Published root identity#

Download: https://litport.net/certificates/litport-cache-root.crt

Machine-readable identity (optional): litport-cache-root.json

Field Value
Subject O=Litport, CN=Litport cache root CA
Issuer O=Litport, CN=Litport cache root CA
PEM format PEM-encoded X.509 certificate
Valid from (UTC) 2026-09-08T18:54:30.000Z
Valid to (UTC) 2036-09-08T18:59:30.000Z
X.509 SHA-256 fingerprint 6E:0D:49:97:67:B0:D5:E3:41:E3:C7:B8:CC:65:85:C2:FD:04:EE:64:E7:64:E8:5A:79:18:27:F6:DD:1E:FD:38
Downloaded PEM file SHA-256 b5a687754f15ab2fe7a00fc77738bc8f9e608e890159e4eccf5cbd48a46a9b7a

The fingerprint hashes the certificate's DER representation. The file checksum hashes the downloaded PEM bytes, including textual encoding and line endings, so these SHA-256 values differ.

curl --fail --remote-name https://litport.net/certificates/litport-cache-root.crt
openssl x509 -in litport-cache-root.crt -noout -subject -issuer -dates -fingerprint -sha256
sha256sum litport-cache-root.crt

The download contains public certificate material, never a private key. One root works for every selected hub. A hub switch can cause a cache miss because entries are hub-local; it does not require a new root.

What installing the root permits#

The public root allows your client to validate target certificates issued by Litport's cache CA hierarchy. The same root also validates the certificate a hub presents on its https:// proxy endpoint; see HTTP vs HTTPS proxy endpoint. Litport keeps the root private key offline; it is not deployed to hubs. Each hub receives its own intermediate certificate and private key, so the root key is not exposed if one hub is compromised.

For a cache-enabled connection, the selected hub can read the HTTPS request and response. Installing the root system-wide also makes every application using that system store accept certificates issued by the Litport cache hierarchy. Scope trust to the cache client or its dedicated container, use cache mode only for public static data, and remove the root when the workload no longer needs it. Without a valid _cache- suffix, Litport keeps the HTTPS tunnel opaque even if the root remains installed.

Client setup#

Prefer per-process, per-profile, or dedicated-container trust. System trust is broad: all applications using that store can trust certificates issued by this root. Replace USER, PASSWORD, and PORT; percent-encode reserved URL characters and never commit proxy secrets.

curl

curl --proxy 'http://hub-us-7.litport.net:PORT' \
  --proxy-user 'USER:PASSWORD_cache-scripts' \
  --cacert ./litport-cache-root.crt \
  'https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js'

Python

import requests

requests.get(
    "https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js",
    proxies={"https": "http://USER:[email protected]:PORT"},
    verify="litport-cache-root.crt",
    timeout=30,
)

Node

NODE_EXTRA_CA_CERTS=./litport-cache-root.crt node scraper.js

// Configure the Litport HTTP proxy in your Node client.
// Keep rejectUnauthorized at its default true.

Browser automation

// Trust litport-cache-root.crt in the isolated browser/profile
// trust store actually used by the automation browser.
// Keep ignoreHTTPSErrors: false.
// Do not use --ignore-certificate-errors.

Go

pool, _ := x509.SystemCertPool()
pem, _ := os.ReadFile("litport-cache-root.crt")
pool.AppendCertsFromPEM(pem)
transport := &http.Transport{
    Proxy: http.ProxyURL(proxyURL),
    TLSClientConfig: &tls.Config{RootCAs: pool, MinVersion: tls.VersionTLS12},
}

Java

keytool -importcert -alias litport-cache \
  -file litport-cache-root.crt \
  -keystore ./litport-cache-truststore.p12 \
  -storetype PKCS12

java -Djavax.net.ssl.trustStore=./litport-cache-truststore.p12 App

Android

<network-security-config>
  <base-config>
    <trust-anchors><certificates src="system" /></trust-anchors>
  </base-config>
  <debug-overrides>
    <trust-anchors>
      <certificates src="@raw/litport_cache_root" />
    </trust-anchors>
  </debug-overrides>
</network-security-config>

iPhone / iPad

1. Install the Litport root profile.
2. Open Settings → General → About → Certificate Trust Settings.
3. Enable full trust for the Litport root.
4. Remove the profile when cache-mode testing is finished.

curl#

--cacert replaces curl's default CA bundle for this request. Combine required roots in a dedicated bundle if the target needs another private CA.

curl --proxy 'http://hub-us-7.litport.net:PORT' --proxy-user 'USER:PASSWORD_cache-scripts' \
  --cacert ./litport-cache-root.crt --verbose \
  'https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js'

Python Requests, httpx, and aiohttp#

Requests' verify file replaces its default bundle. For httpx and aiohttp, create the default context first, then call load_verify_locations() to append this root to the system roots.

import asyncio, ssl
import aiohttp, httpx, requests
proxy = 'http://USER:[email protected]:PORT'
url = 'https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js'
requests.get(url, proxies={'https': proxy}, verify='litport-cache-root.crt', timeout=30)
context = ssl.create_default_context()
context.load_verify_locations(cafile='litport-cache-root.crt')
httpx.get(url, proxy=proxy, verify=context, timeout=30)
async def fetch():
    async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl=context)) as session:
        async with session.get(url, proxy=proxy) as response: return await response.read()
asyncio.run(fetch())

Node HTTPS clients#

NODE_EXTRA_CA_CERTS appends roots to Node. A real HTTPS proxy agent routes traffic; keep rejectUnauthorized at its default true.

npm install https-proxy-agent
NODE_EXTRA_CA_CERTS=./litport-cache-root.crt node scraper.mjs
import https from 'node:https'
import { HttpsProxyAgent } from 'https-proxy-agent'
const agent = new HttpsProxyAgent('http://USER:[email protected]:PORT')
https.get('https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js', { agent }, response => response.resume())

This setting does not configure Chromium, Playwright, or Puppeteer traffic.

Browser automation#

Install the root in the isolated browser profile's OS or NSS store. Keep ignoreHTTPSErrors: false and do not use --ignore-certificate-errors.

import { chromium } from 'playwright'
const browser = await chromium.launch({ proxy: {
  server: 'http://hub-us-7.litport.net:PORT', username: 'USER', password: 'PASSWORD_cache-scripts',
}})
const context = await browser.newContext({ ignoreHTTPSErrors: false })
await (await context.newPage()).goto('https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js')

Go#

pool, err := x509.SystemCertPool()
if err != nil || pool == nil { pool = x509.NewCertPool() }
pem, err := os.ReadFile("litport-cache-root.crt")
if err != nil || !pool.AppendCertsFromPEM(pem) { log.Fatal("could not add Litport root") }
proxyURL, err := url.Parse("http://USER:[email protected]:PORT")
if err != nil { log.Fatal(err) }
client := &http.Client{Transport: &http.Transport{
  Proxy: http.ProxyURL(proxyURL),
  TLSClientConfig: &tls.Config{RootCAs: pool, MinVersion: tls.VersionTLS12},
}}
response, err := client.Get("https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js")

SystemCertPool plus AppendCertsFromPEM preserves system roots and appends this root.

Java#

A dedicated truststore is process-scoped, but replaces Java's default bundle. Import other required roots into that dedicated store.

keytool -importcert -noprompt -alias litport-cache -file litport-cache-root.crt \
  -keystore ./litport-cache-truststore.p12 -storetype PKCS12 -storepass changeit
java -Djavax.net.ssl.trustStore=./litport-cache-truststore.p12 \
  -Djavax.net.ssl.trustStoreType=PKCS12 -Djavax.net.ssl.trustStorePassword=changeit App

Install and remove from broad trust stores#

Use these only when process/profile trust is unavailable; they affect other applications too.

Debian and Ubuntu#

sudo install -m 0644 litport-cache-root.crt /usr/local/share/ca-certificates/litport-cache-root.crt
sudo update-ca-certificates
# Remove: sudo rm /usr/local/share/ca-certificates/litport-cache-root.crt && sudo update-ca-certificates

RHEL and Fedora#

sudo install -m 0644 litport-cache-root.crt /etc/pki/ca-trust/source/anchors/litport-cache-root.crt
sudo update-ca-trust extract
# Remove: sudo rm /etc/pki/ca-trust/source/anchors/litport-cache-root.crt && sudo update-ca-trust extract

macOS#

sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain litport-cache-root.crt
# Remove: sudo security delete-certificate -c 'Litport cache root CA' /Library/Keychains/System.keychain

Windows#

Run in elevated PowerShell:

certutil -addstore -f Root .\litport-cache-root.crt
# Remove: certutil -delstore Root "Litport cache root CA"

Firefox and NSS#

Set FIREFOX_PROFILE to the profile directory with cert9.db; on Debian/Ubuntu install libnss3-tools first.

certutil -A -n 'Litport cache root' -t 'C,,' -i litport-cache-root.crt -d "sql:$FIREFOX_PROFILE"
# Remove: certutil -D -n 'Litport cache root' -d "sql:$FIREFOX_PROFILE"

Containers and Kubernetes#

Use a dedicated workload image or read-only runtime mount instead of host trust. For Node:

COPY litport-cache-root.crt /opt/litport/litport-cache-root.crt
ENV NODE_EXTRA_CA_CERTS=/opt/litport/litport-cache-root.crt

A distro system-store update trusts every process in the container. For Kubernetes, create a ConfigMap from the downloaded public PEM, then mount it only into the workload requiring cache mode:

kubectl create configmap litport-cache-root --from-file=litport-cache-root.crt
# Pod template fragment
spec:
  containers:
    - name: client
      env:
        - name: NODE_EXTRA_CA_CERTS
          value: /var/run/litport-ca/litport-cache-root.crt
      volumeMounts:
        - { name: litport-cache-root, mountPath: /var/run/litport-ca, readOnly: true }
  volumes:
    - name: litport-cache-root
      configMap: { name: litport-cache-root }

Android#

Android 7.0+ apps normally do not trust user-added CAs. A bundled CA is narrow: include this PEM in the debug build and trust only it. src="user" trusts every user-installed CA and is broader than most production apps should accept. Android documents these trust sources and debug overrides in Network Security Configuration.

<!-- AndroidManifest.xml -->
<application android:networkSecurityConfig="@xml/network_security_config" />

The release build keeps its normal system roots:

<!-- src/main/res/xml/network_security_config.xml -->
<network-security-config><base-config><trust-anchors><certificates src="system" /></trust-anchors></base-config></network-security-config>

The debug build appends the bundled Litport root:

<!-- src/debug/res/xml/network_security_config.xml -->
<network-security-config>
  <base-config><trust-anchors><certificates src="system" /></trust-anchors></base-config>
  <debug-overrides><trust-anchors><certificates src="@raw/litport_cache_root" /></trust-anchors></debug-overrides>
</network-security-config>

Place the PEM at src/debug/res/raw/litport_cache_root.pem. A third-party app whose trust policy cannot change is incompatible with verified cache mode; remove the _cache- suffix.

iPhone and iPad#

Install the downloaded root profile, then complete installation in Settings → General → VPN & Device Management. In Settings → General → About → Certificate Trust Settings, enable full trust for the Litport root. Remove it through VPN & Device Management → profile → Remove Profile. Managed devices should install and remove the same payload through MDM. An app with its own policy or certificate pinning can still reject the connection. Apple documents the separate full-trust step in Trust manually installed certificate profiles.

Verify the configuration#

  1. Make a no-suffix control request: it needs no root and uses ordinary proxy behavior.
  2. Make the same HTTPS request with a valid cache-enabled password and verification enabled.
  3. Repeat that identical request to the same hub. Inspect cache statistics for a miss then a hit; do not assume proprietary cache headers.
  4. Add --verbose to the verified curl request and confirm that certificate verification succeeds and the displayed issuer belongs to the Litport cache hierarchy.
  5. A hub switch can miss because entries are hub-local; it does not require a new root.
curl --proxy 'http://hub-us-7.litport.net:PORT' --proxy-user 'USER:PASSWORD_cache-scripts' \
  --cacert ./litport-cache-root.crt --verbose --output /dev/null \
  'https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js'

Focused certificate symptoms#

Symptom Cause Fix
unknown authority, unable to get local issuer, or CERTIFICATE_VERIFY_FAILED Caller does not trust the root. Add it to that process, profile, container, or store; keep verification enabled.
curl works, application fails curl's CA setting is scoped to curl. Configure the application's own trust bundle, preserving needed roots.
Browser error Browser/profile uses another store. Install in its actual OS/NSS profile store; retain browser verification.
Pinned app fails Pinning rejects the issued target certificate. Only its owner can alter pins; use ordinary mode.
HTTP target No authenticated origin TLS leg. Use an HTTPS target, not merely an HTTP proxy endpoint.

Rotation and credential safety#

During rotation, verify the new PEM's published fingerprint and file checksum, trust both roots for the stated overlap, test cache mode, then remove the old root from every dedicated bundle, browser profile, image, and managed-device payload after overlap. Use quoted proxy URLs and --proxy-user where available; use a secret store or injected environment variable, percent-encode reserved URL characters, and never commit proxy secrets or password-bearing command history.

Return to the cache quickstart or options and troubleshooting.