xpzouying/xiaohongshu-mcp · error
get qrcode src failed
Error message
get qrcode src failed
What it means
FetchQrcodeImage navigates to the xiaohongshu explore page, checks whether the user is already logged in, and otherwise locates the login QR-code image (.login-container .qrcode-img) and reads its src attribute. 'get qrcode src failed' wraps the rod error from MustElement/Attribute — normally that the QR-code element was not found within rod's default element-wait timeout, so no login dialog was rendered.
Source
Thrown at xiaohongshu/login.go:104
return nil
}
func (a *LoginAction) FetchQrcodeImage(ctx context.Context) (string, bool, error) {
pp := a.page.Context(ctx)
// 导航到小红书首页,这会触发二维码弹窗
pp.MustNavigate("https://www.xiaohongshu.com/explore").MustWaitLoad()
time.Sleep(2 * time.Second)
if exists, _, _ := pp.Has(".main-container .user .link-wrapper .channel"); exists {
return "", true, nil
}
src, err := pp.MustElement(".login-container .qrcode-img").Attribute("src")
if err != nil {
return "", false, errors.Wrap(err, "get qrcode src failed")
}
if src == nil || len(*src) == 0 {
return "", false, errors.New("qrcode src is empty")
}
return *src, false, nil
}
func (a *LoginAction) WaitForLogin(ctx context.Context) bool {
pp := a.page.Context(ctx)
ticker := time.NewTicker(500 * time.Millisecond)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return false
case <-ticker.C:View on GitHub (pinned to 332d196854)
Solutions
- First confirm login state independently: if already logged in, don't call FetchQrcodeImage — check the returned second bool or verify the .channel element yourself
- Replace the fixed time.Sleep(2s) with an explicit wait for the .login-container .qrcode-img selector (rod's Element already polls; extend the page timeout)
- Dump the page HTML (page.MustElement("body").MustHTML()) when this fires to see whether a captcha/slider or a redesigned login modal replaced the QR dialog
- Update the CSS selectors to match the current xiaohongshu login DOM after inspecting the live page
- Check for risk-control/anti-bot interstitials; consider a real browser profile (user data dir) instead of a clean headless one
Example fix
// before
pp.MustNavigate("https://www.xiaohongshu.com/explore").MustWaitLoad()
time.Sleep(2 * time.Second)
// after
pp.MustNavigate("https://www.xiaohongshu.com/explore").MustWaitLoad()
pp.Timeout(30 * time.Second).MustElement(".login-container .qrcode-img") // explicit wait instead of fixed sleep
src, err := pp.Timeout(10*time.Second).Element(".login-container .qrcode-img") Defensive patterns
Strategy: validation
Validate before calling
// check login state before requesting a QR code
exists, q, err := page.Has(".main-container .user .link-wrapper .channel")
if err == nil && exists { return "", true, nil } // already logged in Type guard
func qrDialogVisible(p *rod.Page) bool {
el, err := p.Timeout(2*time.Second).Element(".login-container .qrcode-img")
return err == nil && el != nil
} Try / catch
src, loggedIn, err := login.FetchQrcodeImage(ctx)
if err != nil {
if strings.Contains(err.Error(), "get qrcode src failed") {
// dialog absent: maybe already logged in or a captcha page; inspect page HTML
html, _ := page.Element("body")
log.Printf("login page state: %v", html)
}
return err
} Prevention
- Short-circuit on logged-in state before calling FetchQrcodeImage
- Expect selector drift: xiaohongshu's login modal DOM can change without notice
- On headless runs, watch for risk-control slider pages replacing the QR dialog
- Use a persistent browser profile so repeat runs are often already logged in
When it happens
Trigger: Calling FetchQrcodeImage while already logged in but the .channel presence check (Has) misses due to selector drift, so the code proceeds to look for a QR dialog that never appears; the login dialog renders slowly or under a different class name after a site update; anti-bot measures show a slider/captcha instead of the QR code; the page failed to fully load in the 2s fixed sleep window.
Common situations: Reusing a session cookie so no QR appears but the login-status selector changed; running headless and getting a risk-control page instead of the normal login modal; xiaohongshu renaming .login-container/.qrcode-img in a front-end release; slow network making 2 seconds insufficient for the modal.
Related errors
AI-assisted analysis of xpzouying/xiaohongshu-mcp@332d196854 (2026-09-05).
Data as JSON: /api/errors/5330da01279f1cf2.
Report an issue: GitHub.