SURF - Advanced Go HTTP client with Chrome/Firefox browser impersonation, HTTP/3 with QUIC fingerprinting, JA3/JA4 TLS emulation, and anti-bot bypass for web au
SURF - Advanced Go HTTP client with Chrome/Firefox browser impersonation, HTTP/3 with QUIC fingerprinting, JA3/JA4 TLS emulation, and anti-bot bypass for web au
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.
HelloID and HelloSpecnet/http.Client for third-party library integrationgo get -u github.com/enetx/surfRequired Go version: 1.27+
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():
Limitations with Std():
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())
}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)
}client := surf.NewClient().
Builder().
Impersonate().
Chrome(). // Latest Chrome v152
Build().
Unwrap()
resp := client.Get("https://example.com").Do()client := surf.NewClient().
Builder().
Impersonate().
RandomOS(). // Randomly selects Windows, macOS, Linux, Android, or iOS
Firefox(). // Latest Firefox v148
Build().
Unwrap()// iOS Chrome
client := surf.NewClient().
Builder().
Impersonate().
IOS().
Chrome().
Build().
Unwrap()
// Android Chrome
client := surf.NewClient().
Builder().
Impersonate().
Android().
Chrome().
Build().
Unwrap()// 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 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()// Custom fingerprint settings
client := surf.NewClient().
Builder().
HTTP3Settings().Grease().Set().
Build().
Unwrap()
HTTP/3 automatically handles compatibility issues:
…Key HTTP/3 Features:
ForceHTTP3() works regardless of call order// 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()client := surf.NewClient().
Builder().
HTTP2Settings().
HeaderTableSize(65536).
EnablePush(0).
InitialWindowSize(6291456).
MaxHeaderListSize(262144).
ConnectionFlow(15663105).
Set().
Build().
Unwrap()client := surf.NewClient().
Builder().
HTTP3Settings().
QpackMaxTableCapacity(65536).
MaxFieldSectionSize(262144).
QpackBlockedStreams(100).
H3Datagram(1).
Grease().
Set().
Build().
Unwrap()// Single proxy
client := surf.NewClient().
Builder().
Proxy("http://proxy.example.com:8080").
Build().
Unwrap()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()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()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 := surf.NewClient().
Builder().
With(func(client *surf.Client) error {
// Modify client configuration
client.GetClient().Timeout = 30 * time.Second
return nil
}).
Build().
Unwrap()user := map[string]string{
"name": "John Doe",
"email": "[email protected]",
}
resp := surf.NewClient().
Post("https://api.example.com/users").
Body(user).
Do()// 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()// 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()…client := surf.NewClient().
Builder().
Session(). // Enable cookie jar
Build().
Unwrap()
// Login
client.Post("https://example.com/login").Body(credentials).Do()
// Subsequent requests will include session cookies
resp := client.Get("https://example.com/dashboard").Do()// Set cookies
cookies := []*http.Cookie{
{Name: "session", Value: "abc123"},
{Name: "preference", Value: "dark_mode"},
}
resp := surf.NewClient().
Get("https://example.com").
AddCookies(cookies...).
Do()
// Get cookies from response
if resp.IsOk() {
for _, cookie := range resp.Ok().Cookies {
fmt.Printf("Cookie: %s = %s\n", cookie.Name, cookie.Value)
}
}resp := surf.NewClient().Get("htNo open issues yet, or sync has not completed.