enetx/surf README
- title
- enetx/surf README
- source_url
- https://github.com/enetx/surf
- fetched
- 2026-05-06
SURF - Advanced Go HTTP Client
Repo: enetx/surf Language: Go (100%) License: MIT Stars: 1.7k (88 forks) Required Go version: 1.25+
SURF is an advanced HTTP client library for Go featuring Chrome/Firefox browser impersonation, HTTP/3 with QUIC fingerprinting, JA3/JA4 TLS emulation, and anti-bot bypass capabilities for web automation and scraping.
Key Features
Browser Impersonation
- Mimics Chrome v145 and Firefox v148 fingerprints accurately
- Cross-platform: Windows, macOS, Linux, Android, iOS
- Automatic header ordering and browser-specific values
- WebKit form boundary generation matching real browsers
Advanced TLS & Security
- Custom JA3/JA4 fingerprint configuration via HelloID and HelloSpec
- Full HTTP/3 over QUIC support with complete browser fingerprinting
- HTTP/2 with customizable SETTINGS frames and window sizes
- DNS-over-TLS (DoT)
- Proxy: HTTP, HTTPS, SOCKS4, SOCKS5 with UDP for HTTP/3
- Certificate pinning
Performance & Reliability
- Connection pooling with singleton pattern
- Configurable automatic retry logic
- Response body caching
- Streaming support (large responses + SSE)
- Automatic decompression (gzip, deflate, brotli, zstd)
Developer Experience
- Standard library compatibility (converts to
*net/http.Client) - Fluent, chainable API
- Extensible middleware system with priority support
- Strong typing with generics via enetx/g
- Comprehensive debug mode
- Full context.Context integration
Installation
go get -u github.com/enetx/surf
Usage
Basic GET
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())
Browser Impersonation
client := surf.NewClient().Builder().Impersonate().Chrome().Build().Unwrap()
client := surf.NewClient().Builder().Impersonate().RandomOS().Firefox().Build().Unwrap()
client := surf.NewClient().Builder().Impersonate().IOS().Chrome().Build().Unwrap()
HTTP/3
client := surf.NewClient().Builder().
Impersonate().Chrome().
ForceHTTP3().
Build().Unwrap()
resp := client.Get("https://cloudflare-quic.com/").Do()
fmt.Printf("Protocol: %s\n", resp.Ok().Proto) // HTTP/3.0
Custom JA3
client := surf.NewClient().Builder().JA().Chrome().Build().Unwrap()
client := surf.NewClient().Builder().JA().Randomized().Build().Unwrap()
HTTP/2 Settings
client := surf.NewClient().Builder().
HTTP2Settings().
HeaderTableSize(65536).
EnablePush(0).
InitialWindowSize(6291456).
Set().
Build().Unwrap()
Proxies
client := surf.NewClient().Builder().Proxy("http://proxy.example.com:8080").Build().Unwrap()
// SOCKS5 UDP for HTTP/3
client := surf.NewClient().Builder().
Proxy("socks5://127.0.0.1:1080").
ForceHTTP3().
Build().Unwrap()
Sessions
client := surf.NewClient().Builder().Session().Build().Unwrap()
client.Post("https://example.com/login").Body(credentials).Do()
resp := client.Get("https://example.com/dashboard").Do()
Middleware
client := surf.NewClient().Builder().
With(func(req *surf.Request) error {
req.AddHeaders("X-Custom-Header", "value")
return nil
}).
Build().Unwrap()
Multipart Upload
mp := surf.NewMultipart().
Field("description", "Multiple files").
File("document", g.NewFile("/path/to/doc.pdf")).
FileBytes("data", "data.json", g.Bytes(`{"key": "value"}`)).
FileString("text", "note.txt", "Hello, World!")
resp := surf.NewClient().Post("https://api.example.com/upload").Multipart(mp).Do()
Streaming + SSE
resp := surf.NewClient().Get("https://example.com/large-file").Do()
stream := resp.Ok().Body.Stream()
defer stream.Close()
scanner := bufio.NewScanner(stream)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
// SSE
resp.Ok().Body.SSE(func(event *sse.Event) bool {
fmt.Printf("Event: %s, Data: %s\n", event.Event, event.Data)
return true
})
Standard library compatibility
surfClient := surf.NewClient().Builder().Impersonate().Chrome().Session().Build().Unwrap()
stdClient := surfClient.Std()
resp, err := stdClient.Get("https://api.example.com")
Preserved when using Std(): JA3/TLS fingerprinting, HTTP/2/3 settings, browser headers, ordered headers, cookies/sessions, proxy, custom headers, timeout, redirect policies, request/response middleware.
Lost when using Std(): retry logic, response body caching, remote address tracking, request timing.
Other features
- H2C (HTTP/2 Cleartext):
.H2C() - Custom DNS:
.DNS("8.8.8.8:53") - DNS-over-TLS:
.DNSOverTLS().Cloudflare() - Unix sockets:
.UnixSocket("/var/run/docker.sock") - Interface binding:
.InterfaceAddr("192.168.1.100") - Raw HTTP requests:
client.Raw(rawRequest, "https").Do() - Retry:
.Retry(3, 2*time.Second) - Body caching:
.CacheBody()
Architecture
- Result type pattern: operations return
g.Result[T]; explicit error handling without panic. - Middleware system: request, response, and client-level with priority-based ordering.
- Fluent builder: method chaining for client construction.
- Connection pooling: singleton pattern for connection reuse.
- Compatibility layer: convertable to
*net/http.Clientretaining most features. - Fingerprinting foundation: built on uTLS (refraction-networking) for JA3/JA4, quic-go for QUIC.
HTTP/3 & QUIC
- Complete QUIC fingerprinting matching Chrome/Firefox
- Header ordering preserved for browser-like sequences
- SOCKS5 UDP proxy support for HTTP/3
- Automatic fallback to HTTP/2 with HTTP proxies
- DNS integration with custom DNS and DoT
- JA4QUIC support with Initial Packet + TLS ClientHello
Dependencies
- enetx/http: enhanced HTTP functionality
- quic-go: HTTP/3 & QUIC
- uTLS (refraction-networking): TLS fingerprinting
- enetx/g: generic utilities, Result type