MCPcopy Index your code
hub / github.com/enetx/surf

github.com/enetx/surf @v1.0.202

Chat with this repo
repository ↗ · DeepWiki ↗ · release v1.0.202 ↗ · + Follow
1,269 symbols 12,495 edges 150 files 450 documented · 35% 1 cross-repo links
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Surf - Advanced HTTP Client for Go

Go Reference Go Report Card Coverage Status Go Mentioned in Awesome Go Ask DeepWiki

Surf is a powerful, feature-rich HTTP client library for Go that makes working with HTTP requests intuitive and enjoyable. With advanced features like browser impersonation, JA3/JA4 fingerprinting, and comprehensive middleware support, Surf provides everything you need for modern web interactions.

✨ Key Features

🎭 Browser Impersonation

  • Chrome & Firefox Support: Accurately mimic Chrome v145 and Firefox v148 browser fingerprints
  • Platform Diversity: Impersonate Windows, macOS, Linux, Android, and iOS devices
  • TLS Fingerprinting: Full JA3/JA4 fingerprint customization for enhanced privacy
  • Automatic Headers: Proper header ordering and browser-specific values
  • WebKit Form Boundaries: Accurate multipart form boundary generation matching real browsers

🔒 Advanced TLS & Security

  • Custom JA3/JA4: Configure precise TLS fingerprints with HelloID and HelloSpec
  • HTTP/3 Support: Full HTTP/3 over QUIC with complete browser-specific fingerprinting
  • HTTP/2 & HTTP/3: Full HTTP/2 support with customizable settings (SETTINGS frame, window size, priority)
  • Ordered Headers: Browser-accurate header ordering for perfect fingerprint evasion
  • Certificate Pinning: Custom TLS certificate validation
  • DNS-over-TLS: Enhanced privacy with DoT support
  • Proxy Support: HTTP, HTTPS, SOCKS4 and SOCKS5 proxy configurations with UDP support for HTTP/3

🚀 Performance & Reliability

  • Connection Pooling: Efficient connection reuse with singleton pattern
  • Automatic Retries: Configurable retry logic with custom status codes
  • Response Caching: Built-in body caching for repeated access
  • Streaming Support: Efficient handling of large responses and SSE
  • Compression: Automatic decompression of gzip, deflate, brotli, and zstd responses
  • Keep-Alive: Persistent connections with configurable parameters

🛠️ Developer Experience

  • Standard Library Compatible: Convert to net/http.Client for third-party library integration
  • Fluent API: Chainable methods for elegant code
  • Middleware System: Extensible request/response/client middleware with priority support
  • Type Safety: Strong typing with generics support via enetx/g
  • Debug Mode: Comprehensive request/response debugging
  • Error Handling: Result type pattern for better error management
  • Context Support: Full context.Context integration for cancellation and timeouts

📦 Installation

go get -u github.com/enetx/surf

Required Go version: 1.25+

🔄 Standard Library Compatibility

Surf provides seamless integration with Go's standard net/http package, allowing you to use Surf's advanced features with any library that expects a standard *http.Client.

// Create a Surf client with advanced features
surfClient := surf.NewClient().
    Builder().
    Impersonate().Chrome().
    Session().
    Build().
    Unwrap()

// Convert to standard net/http.Client
stdClient := surfClient.Std()

// Use with any third-party library
// Example: AWS SDK, Google APIs, OpenAI client, etc.
resp, err := stdClient.Get("https://api.example.com")

Preserved Features When Using Std(): - ✅ JA3/TLS fingerprinting - ✅ HTTP/2, HTTP/3 settings && fingerprinting - ✅ Browser impersonation headers - ✅ Ordered headers - ✅ Cookies and sessions - ✅ Proxy configuration - ✅ Custom headers and User-Agent - ✅ Timeout settings - ✅ Redirect policies - ✅ Request/Response middleware

Limitations with Std(): - ❌ Retry logic (implement at application level) - ❌ Response body caching - ❌ Remote address tracking - ❌ Request timing information

🚀 Quick Start

Basic GET Request

package main

import (
    "fmt"
    "log"
    "github.com/enetx/surf"
)

func main() {
    resp := surf.NewClient().Get("https://api.github.com/users/github").Do()
    if resp.IsErr() {
        log.Fatal(resp.Err())
    }

    fmt.Println(resp.Ok().Body.String().Unwrap())
}

JSON Response Handling

type User struct {
    Name     string `json:"name"`
    Company  string `json:"company"`
    Location string `json:"location"`
}

resp := surf.NewClient().Get("https://api.github.com/users/github").Do()
if resp.IsOk() {
    var user User
    resp.Ok().Body.JSON(&user)
    fmt.Printf("User: %+v\n", user)
}

🎭 Browser Impersonation

Chrome Impersonation

client := surf.NewClient().
    Builder().
    Impersonate().
    Chrome().        // Latest Chrome v145
    Build().
    Unwrap()

resp := client.Get("https://example.com").Do()

Firefox with Random OS

client := surf.NewClient().
    Builder().
    Impersonate().
    RandomOS().      // Randomly selects Windows, macOS, Linux, Android, or iOS
    Firefox().       // Latest Firefox v148
    Build().
    Unwrap()

Platform-Specific Impersonation

// iOS Chrome
client := surf.NewClient().
    Builder().
    Impersonate().
    IOS().
    Chrome().
    Build().
    Unwrap()

// Android Chrome
client := surf.NewClient().
    Builder().
    Impersonate().
    Android().
    Chrome().
    Build().
    Unwrap()

🚀 HTTP/3 & Complete QUIC Fingerprinting

Chrome HTTP/3 with Automatic Detection

// Automatic HTTP/3 with Chrome fingerprinting
client := surf.NewClient().
    Builder().
    Impersonate().Chrome().
    ForceHTTP3().    // Auto-detects Chrome and applies appropriate HTTP/3 settings
    Build().
    Unwrap()

resp := client.Get("https://cloudflare-quic.com/").Do()
if resp.IsOk() {
    fmt.Printf("Protocol: %s\n", resp.Ok().Proto) // HTTP/3.0
}

Firefox HTTP/3

// Firefox with HTTP/3 fingerprinting
client := surf.NewClient().
    Builder().
    Impersonate().Firefox().
    ForceHTTP3().    // Auto-detects Firefox and applies Firefox HTTP/3 settings
    Build().
    Unwrap()

resp := client.Get("https://cloudflare-quic.com/").Do()

Manual HTTP/3 Configuration

// Custom fingerprint settings
client := surf.NewClient().
    Builder().
    HTTP3Settings().Grease().Set().
    Build().
    Unwrap()

HTTP/3 Compatibility & Fallbacks

HTTP/3 automatically handles compatibility issues:

// With HTTP proxy - automatically falls back to HTTP/2
client := surf.NewClient().
    Builder().
    Proxy("http://proxy:8080").    // HTTP proxies incompatible with HTTP/3
    ForceHTTP3().                  // Will use HTTP/2 instead
    Build().
    Unwrap()

// With SOCKS5 proxy - HTTP/3 works over UDP
client := surf.NewClient().
    Builder().
    Proxy("socks5://127.0.0.1:1080").    // SOCKS5 UDP proxy supports HTTP/3
    ForceHTTP3().                        // Will use HTTP/3 over SOCKS5
    Build().
    Unwrap()

// With DNS settings - works seamlessly
client := surf.NewClient().
    Builder().
    DNS("8.8.8.8:53").   // Custom DNS works with HTTP/3
    ForceHTTP3().
    Build().
    Unwrap()

// With DNS-over-TLS - works seamlessly
client := surf.NewClient().
    Builder().
    DNSOverTLS().Google().   // DoT works with HTTP/3
    ForceHTTP3()
    Build().
    Unwrap()

Key HTTP/3 Features: - ✅ Complete QUIC Fingerprinting: Full Chrome and Firefox QUIC transport parameter matching - ✅ Header Ordering: Perfect browser-like header sequence preservation - ✅ SOCKS5 UDP Support: HTTP/3 works seamlessly over SOCKS5 UDP proxies - ✅ Automatic Fallback: Smart fallback to HTTP/2 when HTTP proxies are configured - ✅ DNS Integration: Custom DNS and DNS-over-TLS support - ✅ JA4QUIC Support: Advanced QUIC fingerprinting with Initial Packet + TLS ClientHello - ✅ Order Independence: ForceHTTP3() works regardless of call order

🔧 Advanced Configuration

Custom JA3 Fingerprint

// Use specific browser versions
client := surf.NewClient().
    Builder().
    JA().
    Chrome().     // Latest Chrome
    Build().
    Unwrap()


// Randomized fingerprints for evasion
client := surf.NewClient().
    Builder().
    JA().
    Randomized().    // Random TLS fingerprint
    Build().
    Unwrap()

// With custom HelloID
client := surf.NewClient().
    Builder().
    JA().
    SetHelloID(utls.HelloChrome_Auto).
    Build().
    Unwrap()

// With custom HelloSpec
client := surf.NewClient().
    Builder().
    JA().
    SetHelloSpec(customSpec).
    Build().
    Unwrap()

HTTP/2 Configuration

client := surf.NewClient().
    Builder().
    HTTP2Settings().
    HeaderTableSize(65536).
    EnablePush(0).
    InitialWindowSize(6291456).
    MaxHeaderListSize(262144).
    ConnectionFlow(15663105).
    Set().
    Build().
    Unwrap()

HTTP/3 Configuration

client := surf.NewClient().
    Builder().
    HTTP3Settings().
    QpackMaxTableCapacity(65536).
    MaxFieldSectionSize(262144).
    QpackBlockedStreams(100).
    H3Datagram(1).
    Grease().
    Set().
    Build().
    Unwrap()

Proxy Configuration

// Single proxy
client := surf.NewClient().
    Builder().
    Proxy("http://proxy.example.com:8080").
    Build().
    Unwrap()

SOCKS5 UDP Proxy Support

Surf supports HTTP/3 over SOCKS5 UDP proxies, combining the benefits of modern QUIC protocol with proxy functionality:

// HTTP/3 over SOCKS5 UDP proxy
client := surf.NewClient().
    Builder().
    Proxy("socks5://127.0.0.1:1080").
    Impersonate().Chrome().
    ForceHTTP3().  // Uses HTTP/3 over SOCKS5 UDP
    Build().
    Unwrap()

// SOCKS5 with custom DNS resolution
client := surf.NewClient().
    Builder().
    DNS("8.8.8.8:53").              // Custom DNS resolver
    Proxy("socks5://proxy:1080").   // SOCKS5 UDP proxy
    ForceHTTP3().                   // HTTP/3 over SOCKS5
    Build().
    Unwrap()

🔌 Middleware System

Request Middleware

client := surf.NewClient().
    Builder().
    With(func(req *surf.Request) error {
        req.AddHeaders("X-Custom-Header", "value")
        fmt.Printf("Request to: %s\n", req.GetRequest().URL)
        return nil
    }).
    Build().
    Unwrap()

Response Middleware

client := surf.NewClient().
    Builder().
    With(func(resp *surf.Response) error {
        fmt.Printf("Response status: %d\n", resp.StatusCode)
        fmt.Printf("Response time: %v\n", resp.Time)
        return nil
    }).
    Build().
    Unwrap()

Client Middleware

client := surf.NewClient().
    Builder().
    With(func(client *surf.Client) error {
        // Modify client configuration
        client.GetClient().Timeout = 30 * time.Second
        return nil
    }).
    Build().
    Unwrap()

📤 Request Types

POST with JSON

user := map[string]string{
    "name": "John Doe",
    "email": "john@example.com",
}

resp := surf.NewClient().
    Post("https://api.example.com/users").
    Body(user).
    Do()

Form Data

// Standard form data (field order not guaranteed)
formData := map[string]string{
    "username": "john",
    "password": "secret",
}

resp := surf.NewClient().
    Post("https://example.com/login").
    Body(formData).
    Do()

// Ordered form data (preserves field insertion order)
orderedForm := g.NewMapOrd[string, string]()
orderedForm.Insert("username", "john")
orderedForm.Insert("password", "secret")
orderedForm.Insert("remember_me", "true")

resp := surf.NewClient().
    Post("https://example.com/login").
    Body(orderedForm).
    Do()

File Upload

// Single file upload
mp := surf.NewMultipart().
    File("file", g.NewFile("/path/to/file.pdf"))

resp := surf.NewClient().
    Post("https://api.example.com/upload").
    Multipart(mp).
    Do()

// With additional form fields
mp := surf.NewMultipart().
    Field("description", "Important document").
    Field("category", "reports").
    File("file", g.NewFile("/path/to/file.pdf"))

resp := surf.NewClient().
    Post("https://api.example.com/upload").
    Multipart(mp).
    Do()

Multipart Form

// Simple multipart form with fields only
mp := surf.NewMultipart().
    Field("field1", "value1").
    Field("field2", "value2")

resp := surf.NewClient().
    Post("https://api.example.com/form").
    Multipart(mp).
    Do()

// Advanced multipart with files from different sources
mp := surf.NewMultipart().
    Field("description", "Multiple files").
    File("document", g.NewFile("/path/to/doc.pdf")).               // Physical file
    FileBytes("data", "data.json", g.Bytes(`{"key": "value"}`)).   // Bytes with custom filename
    FileString("text", "note.txt", "Hello, World!").               // String content
    FileReader("stream", "upload.bin", someReader).                // io.Reader
    ContentType("application/pdf")                                 // Custom Content-Type for last file

resp := surf.NewClient().
    Post("https://api.example.com/upload").
    Multipart(mp).
    Do()

🔄 Session Management

Persistent Sessions

```go client := surf.NewClient(). Builder(). Session(). // Enable cookie jar Build(). Unwrap()

// Login client.Post("https://example.com/login").Body(credentials).Do()

// Subsequent request

Extension points exported contracts — how you extend this code

H2Config (Interface)
H2Config is the fluent contract used by profile.ConfigureH2 callbacks. It mirrors the methods on surf.HTTP2Settings, the [2 …
profiles/profile.go
HeadersApplier (FuncType)
HeadersApplier applies the browser-specific request-header pipeline (insert defaults + reorder by header-order map) to a
profiles/headers.go
H3Config (Interface)
H3Config is the fluent contract used by profile.ConfigureH3 callbacks. It mirrors the methods on surf.HTTP3Settings, the [2 …
profiles/profile.go
HeadersFn (FuncType)
HeadersFn is the type of a generic headers function instantiated for a concrete T ~string.
profiles/headers.go

Core symbols most depended-on inside this repo

NewClient
called by 638
client.go
String
called by 629
body.go
Get
called by 629
client.go
Unwrap
called by 560
errors.go
Error
called by 537
errors.go
Do
called by 493
request.go
Build
called by 449
builder.go
Builder
called by 425
client.go

Shape

Function 816
Method 368
Struct 74
TypeAlias 5
Interface 4
FuncType 2

Languages

Go100%

Modules by API surface

tests/http3s_test.go48 symbols
builder.go44 symbols
tests/body_test.go43 symbols
pkg/connectproxy/connectproxy_test.go43 symbols
ja.go42 symbols
tests/builder_test.go40 symbols
tests/request_test.go37 symbols
client.go35 symbols
pkg/quicconn/quic_conn_test.go31 symbols
internal/specclone/specclone_test.go31 symbols
tests/middleware_client_test.go30 symbols
pkg/connectproxy/connectproxy.go30 symbols

Used by 1 indexed graphs manifest dependencies, hub-wide

For agents

$ claude mcp add surf \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page