playwright-community / playwright-go

Playwright for Go a browser automation library to control Chromium, Firefox and WebKit with a single API.
https://playwright-community.github.io/playwright-go/
MIT License
1.94k stars 144 forks source link

Can't change user-agent on headless mode #448

Closed qphuongl closed 1 week ago

qphuongl commented 2 months ago

Hi, I tried to change UserAgent while running headless mode to avoid HeadlessChrome, but it was not working; here is my config:

I ignored the default --headless flag because I want to use --headless=new to access chrome://version after trying --headless (failed).

Actually, I tried to change userAgent in both headless and head mode but it's still not working. But right now, I'm dealing with headless mode.

Spec:

canstand commented 1 month ago

Can't reproduce it. It worked fine in my test.

func TestHeadlessNew(t *testing.T) {
    b2, err := browserType.Launch(playwright.BrowserTypeLaunchOptions{
        Headless: playwright.Bool(false),
        Args: []string{
            "--disable-extensions", "--disable-images", "--window-size=1920,1080", "--start-maximized", "--headless=new",
        },
        IgnoreDefaultArgs: []string{"--enable-automation", "--no-sandbox", "--mute-audio", "--headless", "--disable-features"},
    })
    require.NoError(t, err)
    defer b2.Close()
    nCtx, err := b2.NewContext(playwright.BrowserNewContextOptions{
        UserAgent: playwright.String("foobar/1.0"),
    })
    require.NoError(t, err)
    defer nCtx.Close()
    nPage, err := nCtx.NewPage()
    require.NoError(t, err)

    resChan := server.WaitForRequestChan("/empty.html")
    _, err = nPage.Goto(server.PREFIX + "/empty.html")
    require.NoError(t, err)
    res := <-resChan
    require.True(t, strings.HasPrefix(res.Header.Get("User-Agent"), "foobar"))
}
qphuongl commented 1 week ago

Thanks @canstand, here is my code to create the browser context:

func newChromeContext(savePath string) (playwright.BrowserContext, error) {
    if global.chromeDefault == nil {
        return nil, errors.New("chrome is not initialized")
    }

    browser := *global.chromeDefault

    opts := playwright.BrowserNewContextOptions{}
    opts.UserAgent = playwright.String("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36")
    if savePath != "" && isFileExist(savePath) {
        opts.StorageStatePath = playwright.String(savePath)
    }

    context, err := browser.NewContext(opts)
    if err != nil {
        return nil, fmt.Errorf("create new browser context: %w", err)
    }

    return context, nil
}

And the screenshot that is taken programmatically when I open chrome://version shows that the version still has 'headless'

2024-06-22 10:14:54 204869 +0700 +07 m=+41 120290085

canstand commented 1 week ago

Playwright does not modify the useragent via cli arguments, so the useragent shown in the screenshot is not the same as the request sent when using it.

Also, while digging into this I found an environment variable PLAYWRIGHT_CHROMIUM_USE_HEADLESS_NEW. Use it to avoid using the cli args.

https://github.com/microsoft/playwright/packages/playwright-core/lib/server/chromium/chromium.js

qphuongl commented 1 week ago

Thank you for your help and suggestion; the issue has been resolved. The problem was due to misunderstanding how Playwright handles UserAgent.