Skip to main content

Make your first request

This guide will walk you through installing TLS Client and making your first HTTP request with TLS fingerprinting.
1

Install TLS Client

Add TLS Client to your Go project:
go get github.com/bogdanfinn/tls-client
This will also install the required dependencies:
  • github.com/bogdanfinn/fhttp - Fork of net/http with TLS fingerprinting support
  • github.com/bogdanfinn/utls - TLS library for client fingerprinting
2

Create a basic client

Create a new file main.go with the following code:
main.go
package main

import (
    "fmt"
    "io"
    "log"

    http "github.com/bogdanfinn/fhttp"
    tls_client "github.com/bogdanfinn/tls-client"
    "github.com/bogdanfinn/tls-client/profiles"
)

func main() {
    // Create a cookie jar for automatic cookie handling
    jar := tls_client.NewCookieJar()
    
    // Configure client options
    options := []tls_client.HttpClientOption{
        tls_client.WithTimeoutSeconds(30),
        tls_client.WithClientProfile(profiles.Chrome_144),
        tls_client.WithCookieJar(jar),
    }

    // Create the client
    client, err := tls_client.NewHttpClient(tls_client.NewNoopLogger(), options...)
    if err != nil {
        log.Fatal(err)
    }

    // Make a request
    resp, err := client.Get("https://tls.peet.ws/api/all")
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()

    // Read the response
    body, _ := io.ReadAll(resp.Body)
    fmt.Printf("Status: %d\n%s\n", resp.StatusCode, body)
}
We’re using profiles.Chrome_144 to mimic Chrome 144’s TLS fingerprint. See Browser Profiles for all available profiles.
3

Run your code

Run your program:
go run main.go
You should see a successful response with status 200 and JSON output containing your TLS fingerprint details.

Make a POST request

Here’s how to make a POST request with custom headers:
package main

import (
    "log"
    "net/url"
    "strings"

    http "github.com/bogdanfinn/fhttp"
    tls_client "github.com/bogdanfinn/tls-client"
    "github.com/bogdanfinn/tls-client/profiles"
)

func main() {
    options := []tls_client.HttpClientOption{
        tls_client.WithTimeoutSeconds(30),
        tls_client.WithClientProfile(profiles.Chrome_144),
    }

    client, err := tls_client.NewHttpClient(tls_client.NewNoopLogger(), options...)
    if err != nil {
        log.Fatal(err)
    }

    // Prepare form data
    postData := url.Values{}
    postData.Add("username", "john")
    postData.Add("password", "secret123")

    // Create request
    req, err := http.NewRequest(
        http.MethodPost,
        "https://example.com/api/login",
        strings.NewReader(postData.Encode()),
    )
    if err != nil {
        log.Fatal(err)
    }

    // Set headers with custom order
    req.Header = http.Header{
        "content-type":    {"application/x-www-form-urlencoded"},
        "accept":          {"application/json"},
        "accept-language": {"en-US,en;q=0.9"},
        "user-agent":      {"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"},
        http.HeaderOrderKey: {
            "content-type",
            "accept",
            "accept-language",
            "user-agent",
        },
    }

    // Execute request
    resp, err := client.Do(req)
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()

    log.Printf("Status: %d", resp.StatusCode)
}
Header names in HeaderOrderKey must be lowercase. TLS Client will automatically convert them to ensure proper ordering.

Use with proxies

TLS Client supports HTTP and SOCKS5 proxies:
options := []tls_client.HttpClientOption{
    tls_client.WithTimeoutSeconds(30),
    tls_client.WithClientProfile(profiles.Chrome_144),
    tls_client.WithProxyUrl("http://user:[email protected]:8080"),
}

client, err := tls_client.NewHttpClient(tls_client.NewNoopLogger(), options...)
tls_client.WithProxyUrl("http://user:[email protected]:8080")
You can also change the proxy at runtime:
err := client.SetProxy("http://user:[email protected]:8080")
if err != nil {
    log.Fatal(err)
}

Control redirects

By default, TLS Client follows redirects automatically. You can disable this:
options := []tls_client.HttpClientOption{
    tls_client.WithTimeoutSeconds(30),
    tls_client.WithClientProfile(profiles.Chrome_144),
    tls_client.WithNotFollowRedirects(),
}

client, err := tls_client.NewHttpClient(tls_client.NewNoopLogger(), options...)
Or toggle it at runtime:
// Disable redirect following
client.SetFollowRedirect(false)

// Re-enable it
client.SetFollowRedirect(true)

Enable debug logging

For debugging, you can enable detailed logging:
options := []tls_client.HttpClientOption{
    tls_client.WithTimeoutSeconds(30),
    tls_client.WithClientProfile(profiles.Chrome_144),
    tls_client.WithDebug(),
}

client, err := tls_client.NewHttpClient(tls_client.NewLogger(), options...)
This will log:
  • Request and response headers
  • Cookie operations
  • Raw bytes sent and received over the wire
  • TLS handshake details

Manage cookies

TLS Client includes built-in cookie jar support:
package main

import (
    "fmt"
    "log"
    "net/url"

    tls_client "github.com/bogdanfinn/tls-client"
    "github.com/bogdanfinn/tls-client/profiles"
)

func main() {
    jar := tls_client.NewCookieJar()
    
    options := []tls_client.HttpClientOption{
        tls_client.WithTimeoutSeconds(30),
        tls_client.WithClientProfile(profiles.Chrome_144),
        tls_client.WithCookieJar(jar),
    }

    client, err := tls_client.NewHttpClient(tls_client.NewNoopLogger(), options...)
    if err != nil {
        log.Fatal(err)
    }

    // Make a request - cookies are automatically stored
    resp, err := client.Get("https://example.com")
    if err != nil {
        log.Fatal(err)
    }
    resp.Body.Close()

    // Get cookies for a URL
    u, _ := url.Parse("https://example.com")
    cookies := client.GetCookies(u)
    
    fmt.Printf("Cookies: %v\n", cookies)
}

Next steps

Configuration

Learn about all available client options and how to configure them.

Browser profiles

Explore all available browser profiles and create custom ones.

Advanced usage

Certificate pinning, bandwidth tracking, WebSockets, and more.

Language bindings

Use TLS Client from Node.js, Python, or C# via FFI.

Build docs developers (and LLMs) love