How go-rod Facilitates Browser Automation in xiaohongshu-mcp

The go-rod library serves as the core automation engine in xiaohongshu-mcp, wrapping Chrome DevTools Protocol calls into high-level Go structs that navigate pages, manipulate DOM elements, and execute JavaScript to automate the Xiaohongshu creator platform.

The xiaohongshu-mcp repository provides a programmatic interface to the Xiaohongshu (Little Red Book) creator platform by leveraging go-rod, a Go-based driver for Chrome DevTools Protocol. This open-source tool transforms manual web interactions into automated workflows, using rod.Page and rod.Browser primitives to drive the web interface without native APIs.

Core go-rod Automation Capabilities

The foundation of browser automation in xiaohongshu-mcp relies on go-rod's navigation primitives to load pages and ensure stable interaction states. The NewPublishImageAction function in xiaohongshu/publish.go demonstrates this pattern by navigating to the publish UI and explicitly waiting for DOM stability before proceeding.

// From xiaohongshu/publish.go L38-L55
pp := page.Context(ctx)
pp.MustNavigate("https://creator.xiaohongshu.com/publish/publish")
pp.WaitLoad()
pp.WaitDOMStable()

Each action creates a context-scoped page with timeout boundaries using page.Timeout(300 * time.Second) to bound long-running UI interactions, ensuring that network delays or slow renders do not hang the automation indefinitely.

Element Detection and Interaction

Go-rod provides robust element lookup methods that xiaohongshu-mcp uses to inspect page state and trigger interactions. The library supports page.Element(selector), page.Elements(selector), and page.Has(selector) for existence checks.

In xiaohongshu/login.go, the CheckLoginStatus method verifies authentication by detecting the presence of the user avatar element:

// From xiaohongshu/login.go L25-L33
avatar, err := page.Element(".user-avatar")
if err != nil {
    return false
}
visible, err := avatar.Visible()

For click interactions, the repository uses elem.Click(proto.InputMouseButtonLeft, 1) with retry logic to handle blocked elements. The mustClickPublishTab helper in xiaohongshu/publish.go implements this to navigate between publishing tabs reliably.

Input Handling and File Uploads

Text input and file uploads rely on go-rod's high-level input APIs. The elem.Input(text) method fills form fields, while elem.SetFiles([]string{path}) handles image and video uploads by targeting file input elements directly.

The image publishing workflow in xiaohongshu/publish.go combines these capabilities:

// From xiaohongshu/publish.go L24-L30
fileInput, err := page.Element("input[type=file]")
if err != nil {
    return err
}
fileInput.SetFiles(content.ImagePaths)

Keyboard actions drive complex UI patterns like tag entry. The repository uses page.Keyboard.Press(input.Enter) and elem.KeyActions() to open dropdown menus and confirm selections programmatically.

JavaScript Evaluation and Dynamic Waiting

For operations beyond standard DOM manipulation, xiaohongshu-mcp leverages page.Eval("js code") to execute JavaScript directly in the browser context. This enables visibility checks, original-statement toggles, and modal handling that require inspection of internal application state.

// From xiaohongshu/publish.go L86-L100
page.Eval(`document.querySelector('.original-checkbox').click()`)

Dynamic waiting implementations use custom polling loops combining time.Sleep, page.Has, and elem.Visible to detect modal dialogs, upload completions, and schedule selectors. This pattern appears throughout xiaohongshu/publish.go to synchronize automation steps with asynchronous UI updates.

Architectural Patterns

Context Propagation and Cancellation

Every public method in xiaohongshu-mcp accepts a context.Context parameter, producing a scoped page via pp := a.page.Context(ctx). This design ensures that cancellations propagate to underlying Chrome DevTools Protocol commands, allowing graceful shutdown of browser operations when parent contexts expire.

Action Struct Composition

The repository abstracts go-rod primitives into action structs (LoginAction, PublishAction, SearchAction) that receive a *rod.Page during initialization. This pattern isolates low-level rod calls into reusable helpers while maintaining composable workflows. Complex flows like PublishAction.Publish orchestrate sequential rod operations—upload, tag entry, schedule configuration, and visibility toggling—while keeping each step isolated and testable.

Practical Implementation Examples

QR Code Authentication Flow

The login implementation navigates to the explore page, extracts the QR code source attribute, and polls for the avatar element to detect successful authentication:

login := xiaohongshu.NewLogin(page)

// Fetch QR code for user scanning
qr, logged, err := login.FetchQrcodeImage(context.Background())
if err != nil {
    log.Fatal(err)
}

// Poll until login completes
if !logged {
    ok := login.WaitForLogin(context.Background())
    if !ok {
        log.Fatal("login timeout")
    }
}

Implementation details: FetchQrcodeImage handles element extraction in xiaohongshu/login.go, while WaitForLogin continuously checks for the avatar element presence.

Publishing Image Content

The publishing workflow demonstrates comprehensive go-rod utilization:

pub, err := xiaohongshu.NewPublishImageAction(page)
if err != nil {
    log.Fatal(err)
}

content := xiaohongshu.PublishImageContent{
    Title:      "Travel Diary",
    Content:    "Mountain exploration tips",
    Tags:       []string{"#travel", "#hiking"},
    ImagePaths: []string{"/tmp/photo1.jpg"},
    Visibility: "仅自己可见",
}

err = pub.Publish(context.Background(), content)

This method chains multiple go-rod operations: file upload via SetFiles, text input via Input, keyboard navigation for tags, and JavaScript evaluation for visibility toggles, as implemented in xiaohongshu/publish.go.

The search functionality navigates to query pages and extracts structured data:

search := xiaohongshu.NewSearchAction(page)
profile, err := search.SearchUser(ctx, "target_username")
if err != nil {
    log.Fatal(err)
}

Source: xiaohongshu/user_profile.go implements element queries and attribute extraction using go-rod's selector engine.

Feed Interaction Automation

Like operations combine element state inspection with conditional clicking:

like := xiaohongshu.NewLikeAction(page)
err := like.ToggleLike(ctx, "feed_12345", false)

The implementation in xiaohongshu/like_favorite.go uses elem.Eval to check button state before invoking elem.Click, preventing duplicate actions.

Summary

  • go-rod provides the Chrome DevTools Protocol abstraction layer that enables xiaohongshu-mcp to control the browser programmatically without native platform dependencies.
  • Context-aware page scoping via page.Context(ctx) and page.Timeout() ensures robust cancellation and timeout handling across all automation actions.
  • Action struct patterns wrap low-level rod.Page methods into reusable, testable components like LoginAction and PublishAction.
  • JavaScript evaluation and dynamic polling loops handle complex UI states, modal dialogs, and asynchronous upload processes that standard DOM methods cannot capture.
  • File uploads and keyboard interactions utilize SetFiles and KeyActions to simulate realistic user input sequences for content publishing.

Frequently Asked Questions

What is go-rod and how does it differ from Selenium?

Go-rod is a Go library that drives browsers directly via the Chrome DevTools Protocol (CDP), offering faster execution and lower resource overhead compared to Selenium WebDriver. Unlike Selenium's JSON Wire Protocol, go-rod communicates natively with Chrome's debugging interface, enabling direct access to network monitoring, performance metrics, and JavaScript execution contexts without intermediary translation layers.

How does xiaohongshu-mcp handle authentication timeouts?

The repository implements context-scoped timeouts using page.Timeout(duration) to wrap each authentication attempt. The WaitForLogin method in xiaohongshu/login.go polls for the user avatar element within this timeout window, allowing the automation to fail gracefully if QR code scanning is not completed within the specified duration (typically 300 seconds).

Can go-rod handle file uploads in headless mode for Xiaohongshu?

Yes. The elem.SetFiles([]string{path}) method in go-rod directly manipulates file input elements in the DOM, which works reliably in headless Chrome instances. In xiaohongshu/publish.go, this capability uploads images and videos to the Xiaohongshu creator interface by targeting the hidden file input elements and setting their files property programmatically, bypassing the native file picker dialog.

How does the library manage dynamic UI elements and pop-ups?

Xiaohongshu-mcp employs JavaScript evaluation via page.Eval() combined with polling loops using page.Has() and elem.Visible() to detect dynamic elements. Helper functions like removePopCover and waitForModalClose inspect the DOM state, evaluate visibility conditions, and retry operations until transient UI elements (such as onboarding modals or upload progress indicators) stabilize or disappear.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →