#1198·rod

[Bug] Element.Screenshot wrong when DevicePixelRatio != 1

Author: kviiCreated Jun 12, 2025Updated Sep 8, 2026
Labelsquestion

Rod Version: v0.116.2

The code to demonstrate your question

go
func main() {
	u := launcher.New().Set("window-size", "1600,900").Headless(false).MustLaunch()
	b := rod.New().DefaultDevice(windowsEdge).ControlURL(u).MustConnect()
	p := b.MustPage()

	// 截图百度 logo
	p.MustNavigate("https://www.baidu.com").MustWaitLoad()
	e := p.MustElement("div#lg")
	e.MustScreenshot("out.png") // 截图的时候页面突然“大”了一下
}

var windowsEdge = devices.Device{
	Title:          "Edge Laptop with HiDPI screen",
	Capabilities:   []string{},
	UserAgent:      "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0",
	AcceptLanguage: "en",
	Screen: devices.Screen{
		DevicePixelRatio: 2, // <-- 注意这里
		Horizontal: devices.ScreenSize{
			Width:  1600,
			Height: 900,
		},
		Vertical: devices.ScreenSize{
			Width:  900,
			Height: 1600,
		},
	},
}.Landscape()

What you got

Image

What you expect to see

Image

What have you tried to solve the question

Codes in Element.Screenshot:

https://github.com/go-rod/rod/blob/393ac0d60b53f3c4a9b2a6504d250cbada55b546/element.go#L697-L705

Element 的 Screenshot 是先对页面截图,然后再根据 Element 的 Shape 进行裁切得到的结果。在 DevicePixelRatio 不是 1 的时候 shape.Box() 返回的坐标和实际元素在屏幕截图中的坐标不一致。所以对元素截图有问题。这里应该把尺寸乘以当前的 DevicePixelRatio,比如这样:

go
box := shape.Box()

factor := el.page.browser.defaultDevice.Screen.DevicePixelRatio
// TODO: proto.PageCaptureScreenshot has a Clip option, but it's buggy, so now we do in Go.
return utils.CropImage(bin, quality,
	int(box.X*factor),
	int(box.Y*factor),
	int(box.Width*factor),
	int(box.Height*factor),
)