rodder

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 19, 2026 License: MIT Imports: 12 Imported by: 0

README

rodder

Go Reference

Wrapper around go-rod. It simplifies the boilerplating for creating a remote controlled browser with or without stealth mode. In addition, it provides helper methods to retreive the headers sent by the browser and current cookies from the browser or the current page. This way you can easily setup a http client that mimics a real browser with a initialized cookie jar (for example passing a login page with cloudfare protection before scripting crawling or scraping).

Leakless mod is disable because a lot of AVs detect it as malware. This only means you have to ensure to call Close() on the instanciated browser to properly close it.

Every objects inherits from rod's original objects:

  • Every original methods are available
  • Special (new) helpers methods are added on top of them (check doc)

Download

go get -u github.com/hekmon/rodder

Example

package main

import (
    "fmt"
    "io"
    "net/http"
    "net/http/cookiejar"
    "os"
    "path/filepath"
    "time"

    "github.com/hashicorp/go-cleanhttp"
    "github.com/hekmon/rodder"
    "golang.org/x/net/publicsuffix"
)

func main() {
    // Create a user profil dir to keep sessions between launchs
    userCacheDir, err := os.UserCacheDir()
    if err != nil {
        panic(err)
    }
    profilDir := filepath.Join(userCacheDir, "project-roduserdata")

    // Create and launch the browser (additional env can be nil)
    stealth := true // Activate all the necessary flags and JS injection on page to have anti-bot bypass
    browser, err := rodder.New(profilDir, stealth, rodder.EnvironmentFR)
    if err != nil {
        panic(err)
    }
    defer browser.Close() // IMPORTANT: otherwise some background chromium process will remain even with all pages are closed !

    // Create a stealth page (high level wrapper that inject rod JS stealth script at startup)
    page, err := browser.NewPage()
    if err != nil {
        panic(err)
    }
    defer page.Close() // not necessary but good habit (think closing the browser tab)

    // Use rod as usual (perform login, pass cloudflare challenge, etc... the idea is the set all the needed cookies here)
    if err = page.Navigate("https://bot.sannysoft.com/"); err != nil {
        panic(err)
    }
    if err = page.WaitStable(time.Second); err != nil {
        panic(err)
    }
    time.Sleep(5 * time.Second) // give you the time to check the page within the open browser

    // Let's create a http client that mimics the browser (except the TLS fingerprinting!)
    //// Let's retreive the current browser headers fingerprint (it will open and close a new tab on the remote browser)
    headers, err := browser.GetHeaders()
    if err != nil {
        panic(err)
    }
    //// Create the custom client
    cookiesClient := cleanhttp.DefaultPooledClient()
    //// Associate the client a cookie jar and inject the current page cookies to it
    jar, err := cookiejar.New(&cookiejar.Options{
        PublicSuffixList: publicsuffix.List,
    })
    if err != nil {
        panic(err)
    }
    if err = page.ExtractCookiesTo(jar); err != nil {
        panic(err)
    }
    cookiesClient.Jar = jar
    //// Create a mimic request with the same browser headers
    req, err := http.NewRequest("GET", "https://bot.sannysoft.com/", nil)
    if err != nil {
        panic(err)
    }
    for header, values := range headers {
        for _, value := range values {
            req.Header.Set(header, value)
        }
    }
    //// Execute it and take advantage of our initialized cookie jar
    resp, err := cookiesClient.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()
    //// Enjoy
    fmt.Println(resp.Status)
    fmt.Println()
    data, err := io.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }
    fmt.Println(string(data))
}

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// EnvironmentFR represents the french environment variables to set in the browser process
	EnvironmentFR = []string{
		"TZ=Europe/Paris",
		"LANGUAGE=fr_FR",
		"LC_ALL=fr_FR.UTF-8",
	}
)

Functions

This section is empty.

Types

type Browser

type Browser struct {
	*rod.Browser
	// contains filtered or unexported fields
}

Browser inherits from *rod.Browser and adds some useful methods

func New

func New(userProfilDirectory string, stealth bool, additionalEnv []string) (b *Browser, err error)

New returns a launched and ready to use browser. It won't use the Leakless side process as it is detected as malware by several AV: this means that without a proper call to Close() the browser won't entirely exit and you will need to kill it yourself. Stealth mode will disable the headless mode and will add stealth mode to the browser and pages created with NewPage() to avoid anti-bot detection.

func (*Browser) ExtractCookiesTo

func (b *Browser) ExtractCookiesTo(jar http.CookieJar) (err error)

ExtractCookiesTo extracts all the cookies from the browser and adds them to the jar

func (*Browser) GetHeaders

func (b *Browser) GetHeaders() (headers http.Header, err error)

GetHeaders returns a list of selected headers the browser add to each requests by requesting a mirror request on https://requestmirror.dev. The list is filtered (and modified for some sec-fetch-* headers) to help you make Golang http requests that mimick what a real browser will do with javascript API requests. Don't forget to add your own "accept", "accept-encoding" and "content-type" if necessary. Example: map[

Accept-Language:[fr-FR] Priority:[u=0, i] Sec-Ch-Ua:["Not;A=Brand";v="24", "Chromium";v="128"]
Sec-Ch-Ua-Mobile:[?0] Sec-Ch-Ua-Platform:["Windows"] Sec-Fetch-Dest:[empty] Sec-Fetch-Mode:[cors]
Sec-Fetch-Site:[same-origin] Upgrade-Insecure-Requests:[1]
User-Agent:[Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36]

]

func (*Browser) NewPage

func (b *Browser) NewPage() (page *Page, err error)

NewPage creates a new page and optionally apply stealth mode if enabled in the browser

type Page

type Page struct {
	*rod.Page
}

Page inherits from *rod.Page and adds some useful methods

func (*Page) ExtractCookiesTo

func (p *Page) ExtractCookiesTo(jar http.CookieJar) (err error)

ExtractCookiesTo extracts the cookies from the current page and adds them to the provided jar

func (*Page) GetCookies

func (p *Page) GetCookies() (cookies []*http.Cookie, err error)

GetCookies returns the cookies for the current page

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL