Playwright for Go a browser automation library to control Chromium, Firefox and WebKit with a single API.

Overview

🎭 Playwright for

PkgGoDev License Go Report Card Build Status Join Slack Coverage Status Chromium version Firefox version WebKit version

API reference | Example recipes

Playwright is a Go library to automate Chromium, Firefox and WebKit with a single API. Playwright is built to enable cross-browser web automation that is ever-green, capable, reliable and fast.

Linux macOS Windows
Chromium 90.0.4392.0
WebKit 14.1
Firefox 85.0b5

Headless execution is supported for all the browsers on all platforms.

Installation

go get github.com/mxschmitt/playwright-go

Capabilities

Playwright is built to automate the broad and growing set of web browser capabilities used by Single Page Apps and Progressive Web Apps.

  • Scenarios that span multiple page, domains and iframes
  • Auto-wait for elements to be ready before executing actions (like click, fill)
  • Intercept network activity for stubbing and mocking network requests
  • Emulate mobile devices, geolocation, permissions
  • Support for web components via shadow-piercing selectors
  • Native input events for mouse and keyboard
  • Upload and download files

Example

The following example crawls the current top voted items from Hacker News.

package main

import (
	"fmt"
	"log"

	"github.com/mxschmitt/playwright-go"
)

func main() {
	pw, err := playwright.Run()
	if err != nil {
		log.Fatalf("could not start playwright: %v", err)
	}
	browser, err := pw.Chromium.Launch()
	if err != nil {
		log.Fatalf("could not launch browser: %v", err)
	}
	page, err := browser.NewPage()
	if err != nil {
		log.Fatalf("could not create page: %v", err)
	}
	if _, err = page.Goto("https://news.ycombinator.com"); err != nil {
		log.Fatalf("could not goto: %v", err)
	}
	entries, err := page.QuerySelectorAll(".athing")
	if err != nil {
		log.Fatalf("could not get entries: %v", err)
	}
	for i, entry := range entries {
		titleElement, err := entry.QuerySelector("td.title > a")
		if err != nil {
			log.Fatalf("could not get title element: %v", err)
		}
		title, err := titleElement.TextContent()
		if err != nil {
			log.Fatalf("could not get text content: %v", err)
		}
		fmt.Printf("%d: %s\n", i+1, title)
	}
	if err = browser.Close(); err != nil {
		log.Fatalf("could not close browser: %v", err)
	}
	if err = pw.Stop(); err != nil {
		log.Fatalf("could not stop Playwright: %v", err)
	}
}

More examples

How does it work?

Playwright is a Node.js library which uses:

  • Chrome DevTools Protocol to communicate with Chromium
  • Patched Firefox to communicate with Firefox
  • Patched WebKit to communicate with WebKit

These patches are based on the original sources of the browsers and don't modify the browser behaviour so the browsers are basically the same (see here) as you see them in the wild. The support for different programming languages is based on exposing a RPC server in the Node.js land which can be used to allow other languages to use Playwright without implementing all the custom logic:

The bridge between Node.js and the other languages is basically a Node.js runtime combined with Playwright which gets shipped for each of these languages (around 50MB) and then communicates over stdio to send the relevant commands. This will also download the pre-compiled browsers.

Is Playwright for Go ready?

We are ready for your feedback, but we are still covering Playwright Go with the tests.

Resources

Comments
  • response.Body does not return the byte array

    response.Body does not return the byte array

    This is issue might relates to #141

    The following is an example to reproduce this bug.

    package main
    
    import (
    	"fmt"
    	"log"
    	"time"
    
    	"github.com/mxschmitt/playwright-go"
    )
    
    func main() {
    	pw, err := playwright.Run()
    	if err != nil {
    		log.Fatalf("could not start playwright: %v", err)
    	}
    	browser, err := pw.Chromium.Launch(playwright.BrowserTypeLaunchOptions{Headless: playwright.Bool(false)})
    	if err != nil {
    		log.Fatalf("could not launch browser: %v", err)
    	}
    	page, err := browser.NewPage()
    	if err != nil {
    		log.Fatalf("could not create page: %v", err)
    	}
    	eventsChan := make(chan string)
    	go func(eventsChan chan string) {
    		for c := range eventsChan {
    			fmt.Println(c)
    		}
    	}(eventsChan)
    	page.On("response", func(response playwright.Response) {
    		// the following code block causes the problem
    		// body, err := response.Body()
    		// if err != nil {
    		// 	log.Fatalf("get body failed: %v", err)
    		// }
    		// fmt.Println("body len: ", len(body))
    
    		eventsChan <- fmt.Sprintf("%d %s", response.Status(), response.URL())
    	})
    	if _, err = page.Goto("https://news.ycombinator.com"); err != nil {
    		log.Fatalf("could not goto: %v", err)
    	}
    
    	time.Sleep(3 * time.Second)
    	if err = browser.Close(); err != nil {
    		log.Fatalf("could not close browser: %v", err)
    	}
    	if err = pw.Stop(); err != nil {
    		log.Fatalf("could not stop Playwright: %v", err)
    	}
    }
    
    

    Tested version go.mod

    go 1.16
    
    require github.com/mxschmitt/playwright-go v0.1100.0 // indirect
    
    opened by lotusirous 9
  • Version Packages

    Version Packages

    @kumaraditya303 Thanks for your great work and all your contributions to this repository. For your commit "roll to 1.14" that matches the latest version of Playwright, do you have any plan to version it or publish the release?

    opened by AngangGuo 9
  • Improve versioning with Git tags / GH releases.

    Improve versioning with Git tags / GH releases.

    Hello, thanks for the lib It works great! I faced with some limitations:

    • I would like to avoid downloading https://github.com/mxschmitt/playwright-go/blob/c9d1531e0354a7f267237b3ac55595a8f18170e4/run.go#L29 after every container start. I assumed that playwright is already installed on the official mcr.microsoft.com/playwright:bionic images.

    • It looks like that playwright is installed from an external source https://github.com/mxschmitt/playwright-go/blob/c9d1531e0354a7f267237b3ac55595a8f18170e4/run.go#L15 not the official ones.

    • How can I install a different playwright version? The current is 1.7

    enhancement 
    opened by StarpTech 9
  • [Feature Question] BrowserContext.backgroundPages() doesn't exist? :)

    [Feature Question] BrowserContext.backgroundPages() doesn't exist? :)

    BrowserContext in this example: https://playwright.dev/docs/chrome-extensions/ (from JavaScript) supports "backgroundPages", a way to get handles on extensions.

    Is this supported in Playwright? It isn't from what I can see at the moment from examining the "Generated structs".

    Do you know if this will get added or if there are plans for it to be added?

    Many thanks & appreciate your work, Neil

    enhancement 
    opened by neilspage 7
  • Missing types for page error events.

    Missing types for page error events.

    Hi, I can't see the type definition of the page errors. For example:

    page, _ := browserContext.NewPage()
    page.Once("pageerror", func(err ???) {
    	c.Logger().Errorf("an error on the page was detected: %s", err)
    })
    

    I also recommend using custom function types e.g

    type RequestFailedEventHandler = func(request *Request)
    
    opened by StarpTech 7
  • Getting fatal panic after upgrading to latest commit from release version

    Getting fatal panic after upgrading to latest commit from release version

    Hi,

    We are getting a fatal panic when going to a specific site, that we didn't get on v0.1400.0 Release, and also a commit version after that specified below.

    Latest commit tested that did not have this issue: 7e45483

    All commits we test that are after this commit, we end up with a fatal panic, which did not happen on the same site prior to this. A big difference I can see is that you go from Playwright 1.14.1 -> 1.16.0-next.. So maybe the problem is there?

    Here is the full panic message:

    events.js:377
          throw er; // Unhandled 'error' event
          ^
    
    Error: EPIPE: broken pipe, write
        at Socket._write (internal/net.js:55:25)
        at writeOrBuffer (internal/streams/writable.js:358:12)
        at Socket.Writable.write (internal/streams/writable.js:303:10)
        at Transport.send (C:\Users\osterman01\AppData\Local\ms-playwright-go\1.16.0-next-1631944242000\package\lib\protocol\transport.js:54:21)
        at DispatcherConnection.dispatcherConnection.onmessage (C:\Users\osterman01\AppData\Local\ms-playwright-go\1.16.0-next-1631944242000\package\lib\cli\driver.js:67:57)
        at DispatcherConnection.sendMessageToClient (C:\Users\osterman01\AppData\Local\ms-playwright-go\1.16.0-next-1631944242000\package\lib\dispatchers\dispatcher.js:186:10)
        at BrowserContextDispatcher._dispatchEvent (C:\Users\osterman01\AppData\Local\ms-playwright-go\1.16.0-next-1631944242000\package\lib\dispatchers\dispatcher.js:108:22)
        at CRBrowserContext.<anonymous> (C:\Users\osterman01\AppData\Local\ms-playwright-go\1.16.0-next-1631944242000\package\lib\dispatchers\browserContextDispatcher.js:102:81)
        at CRBrowserContext.emit (events.js:400:28)
        at FrameManager.requestReceivedResponse (C:\Users\osterman01\AppData\Local\ms-playwright-go\1.16.0-next-1631944242000\package\lib\server\frames.js:295:32)
    Emitted 'error' event on Socket instance at:
        at emitErrorNT (internal/streams/destroy.js:106:8)
        at errorOrDestroy (internal/streams/destroy.js:168:7)
        at onwriteError (internal/streams/writable.js:391:3)
        at processTicksAndRejections (internal/process/task_queues.js:84:21)
        at runNextTicks (internal/process/task_queues.js:64:3)
        at processImmediate (internal/timers.js:437:9) {
      errno: -4047,
      syscall: 'write',
      code: 'EPIPE'
    }
    
    Debugger finished with the exit code 0
    
    p2-bug 
    opened by KiqoCode 6
  • Add missing functionality/methods

    Add missing functionality/methods

    Current report (node scripts/validate-interfaces.js):

    Missing API interface functions:

    • [x] BrowserContext.SetHTTPCredentials
    • [x] BrowserContext.StorageState
    • [x] ElementHandle.WaitForElementState
    • [x] ElementHandle.WaitForSelector
    enhancement good first issue 
    opened by mxschmitt 6
  • Always downloading Playwright driver

    Always downloading Playwright driver

    I noticed that in the current master branch it was always downloading the driver. I found the issue, in PlaywrightDriver.isUpToDateDriver It's checking the output of PW, for example:

    /Users/sam/Library/Caches/ms-playwright-go/1.16.0-next-1634703014000/playwright.sh --version
    Version 1.16.0-next
    

    With the constant:

    const playwrightCliVersion = "1.16.0-next-1634703014000"
    

    Using:

    	if bytes.Contains(output, []byte(d.Version)) {
    		return true, nil
    	}
    

    The extra -1634703014000 on the constant is the issue. I've fixed it locally by adding this to the end of isUpToDateDriver:

    	if strings.HasPrefix(string(output), "Version ") {
    		// Get rid of trailing new line
    		outputStr := strings.TrimSpace(string(output))
    		if len(outputStr) > 8 && strings.Contains(d.Version, outputStr[8:]) {
    			return true, nil
    		}
    	}
    

    I'll submit a PR with the change.

    If you have any suggestions for changes I'm happy to change.

    upstream 
    opened by SamHennessy 5
  • [internal]: fix that there is XML in the doc comments

    [internal]: fix that there is XML in the doc comments

    • [ ] fix that there is XML in the doc comments -> it should not be there (was not correct since a few months)
    • [x] fix that there are csharp examples in the generated_interfaces.go
    • [x] Re-introduce EmulateMedia
    p2-bug 
    opened by mxschmitt 5
  • Interface vs Struct

    Interface vs Struct

    Thanks for this great library and your hardwork to make it great.

    From https://pkg.go.dev/github.com/mxschmitt/playwright-go#pkg-index, the methods show out if the type is struct(like Playwright):

    type Playwright
        func Run(options ...*RunOptions) (*Playwright, error)
        func (c *Playwright) Dispose()
        func (p *Playwright) Stop() error
    

    But No method shows out if the type is defined as interface(like Page), we need to go to the type definition to find the available methods.

    type Page
    

    Is it possible to define the Page as struct?

    type Page struct {
        // non export fields
    }
    
    func (*Page) Click(selector string, options ...PageClickOptions) error
    func (*Page) Fill(selector, text string, options ...FrameFillOptions) error
    ... ...
    

    What do you think about it? Thanks.

    feedback 
    opened by AngangGuo 5
  • Not working on WSL 2

    Not working on WSL 2

    Hi,

    I'm using playwright on this project hippokampe specifically in the api module. This app is already tested in vagrant and linux pc, with positive results, but in the case of WSL 2, it's not working properly.

    I debugged the project, and I can conclude that the problem it's raised right here. I don't receive an error but blocks the execution, like an infinite loop.

    Thanks

    triaging 
    opened by davixcky 5
  • could not download driver

    could not download driver

    trying to install the browsers and OS dependencies: % playwright install --with-deps
    2022/11/28 16:08:57 could not download driver: could not check if driver is up2date: could not run driver: exit status 1

    it seems the baseURL get 404. baseURL = "https://playwright.azureedge.net/builds/driver"

    any idea?

    opened by yusong0926 0
  • Audio not being muted in browser?

    Audio not being muted in browser?

    Hi everyone,

    Maybe this is a dumb question, but isn't audio supposed to be muted in browser instances launched by Playwright by default? Whenever video playback occurs during automation, I can still hear the audio channels for it.

    Is there a special way to disable this audio, if it isn't done automatically for us?

    opened by supercom32 0
  • No response from server after launching browser

    No response from server after launching browser

    I run the test on 60+ locations, through personal paid proxies. Each test is run and accesses the array for access to the proxy. A small part of the tests is performed from the first run. Most of it is from 2-3 runs, a small part remains not passed. Here are the errors I get in the html report: page.goto: Navigation failed because page was closed! and page.goto: net::ERR_ABORTED; maybe frame was detached?

    Help me figure out the problems, what's the matter - do I have bad proxies or problems with the code?

    ` //@ts-check import { test } from '@playwright/test'; import { skipMobile } from '../helpers/device-helpers'; import { geolocations } from '../data/geo-massive'; import { scroll } from '../helpers/scroll';

    geolocations.forEach(g=> test.describe( ${g.name} - Checking the opening of the site loading Web, taking into account the array of geolocations, () => { test('test', async ({ browser, browserName, isMobile }) => {

    //skip mobile browser and PWA skipMobile(browserName, isMobile);

    //Settings the test const context = await browser.newContext({ permissions: ['geolocation'], ignoreHTTPSErrors: true, proxy: { server: g.server, username: g.username, password: g.password }, locale: g.localebrowser, })

    // Start test const page = await context.newPage(); await page.setViewportSize({ width: 1440, height: 900 }); await page.goto('https://mysite.com/'); await page.evaluate(scroll, {direction: "down", speed: "slow"}); if(await page.locator('#games_content').count() !== null) { await page.locator('#games_content >> .arcticmodal-close').click(); }; await page.screenshot({ path: browserName + ${g.name} openWebSitePullGeo.png, fullPage: true}); await context.close(); await browser.close(); }); })) `

    opened by ivanqa2022 1
  • get process of a running browser

    get process of a running browser

    I need to monitor energy consumption of a browser (for exemple chromium) testing multiples pages of the database. I want to use django to runnings my tests concurently using playwright to automate the browser testing (i've already use it a little using the JS api), but the tool i use to monitor energy consumption watch a cgroup where the runing process of the browser need to be added. For this purpose, i've checked on the internet if it's possible to get the PID of a browser using PW and it's seem possible using

      const browserServer = await playwright.chromium.launchServer()
      const pid = await browserServer.process().pid
      console.log(pid)
    

    https://stackoverflow.com/questions/62376437/get-pid-of-a-browser-launched-with-playwright

    But i don't found a way to retrieve this information in playwright-go due to the fact that pw.Chromium don't have a function LauchServer and i've don't found an equivalent.

    opened by shobu13 0
Releases(v0.2000.1)
  • v0.2000.1(Apr 27, 2022)

    What's Changed

    • feat: add locator functionality (#238) by @masaushi in https://github.com/playwright-community/playwright-go/pull/267
    • chore: add support for noViewport by @mxschmitt in https://github.com/playwright-community/playwright-go/pull/258
    • chore: rework parallel crawling example by @mxschmitt in https://github.com/playwright-community/playwright-go/pull/261
    • Add platform "mac-arm64" and "linux-arm64" by @zengxs in https://github.com/playwright-community/playwright-go/pull/264
    • chore: add IgnoreDefaultArgs by @zengxs in https://github.com/playwright-community/playwright-go/pull/265
    • chore: fix flaky network tests by @mxschmitt in https://github.com/playwright-community/playwright-go/pull/260

    New Contributors / Special thanks

    • @zengxs made their first contribution in https://github.com/playwright-community/playwright-go/pull/264
    • @masaushi made their first contribution in https://github.com/playwright-community/playwright-go/pull/267

    Thank you to both of you who invested time and effort into the project! 💯

    Full Changelog: https://github.com/playwright-community/playwright-go/compare/v0.2000.0...v0.2000.1

    Source code(tar.gz)
    Source code(zip)
  • v0.2000.0(Mar 12, 2022)

    This version is on pair drive-wise with the upcoming Playwright 1.20 version.

    Breaking change:

    You need to either install the driver+browsers via CLI or via the API. It does not happen automatically anymore.

    Via the CLI:

    go run github.com/playwright-community/playwright-go/cmd/playwright install
    # Or
    go install github.com/playwright-community/playwright-go/cmd/playwright
    playwright install --with-deps
    

    Or via the API:

    err := playwright.Install()
    
    Source code(tar.gz)
    Source code(zip)
  • v0.1400.0(Aug 27, 2021)

  • v0.1400(Aug 26, 2021)

  • v0.1100.0(Mar 28, 2021)

    • feat(install): allow to install and skip certain browser (#113)
    • docs: update link to Playwright API (#114)
    • fix(ElementHandle): don't panic when QuerySelector not exists (#112)
    Source code(tar.gz)
    Source code(zip)
  • v0.192-beta.1(Mar 16, 2021)

  • v0.171.1(Jan 4, 2021)

    Changelog:

    • chore: add Frame.Tap/Page.Tap/Page.Frame methods (#74)
    • chore: update readme on browser roll (#76)
    • chore: add missing methods (Tap/Touchscreen/WebSocket.IsClosed) (#78)
    • chore: restructure tests (#77)
    • feat: add websocket functionality and tests (#79)
    • feat: add Page on pageerror event (#82)
    • chore: waitForEvent cleanup (#81)
    • chore: cleanup inner core iteration 1 (#86)
    • chore: fix flaky websocket tests (#87)
    • tests: added BindingCall tests (#88)
    • tests: add more worker and element tests (#89)
    Source code(tar.gz)
    Source code(zip)
  • v0.171.0(Dec 29, 2020)

Owner
Max Schmitt
Open Source enthusiast, security researcher and full stack web developer.
Max Schmitt
Generate PlantUML diagrams from Chrome or Firefox network inspections

hoofli Generate PlantUML diagrams from Chrome or Firefox network inspections This tool reads browser HAR files stored on your local disk and transform

Pascal Dennerly 6 Nov 15, 2022
End to end functional test and automation framework

Declarative end to end functional testing (endly) This library is compatible with Go 1.12+ Please refer to CHANGELOG.md if you encounter breaking chan

Viant, Inc 226 Nov 30, 2022
A Devtools driver for web automation and scraping

Overview Documentation | API reference Rod is a high-level driver directly based on DevTools Protocol. It's designed for web automation and scraping.

Rod 3.2k Nov 27, 2022
Ritchie CLI is an open-source tool that allows to create, store and share any kind of automation, executing them through command lines, to run operations or start workflows ⚙️ 🖥 💡

Table of contents 1. About 2. Getting Started i. Installation ii. Initialize rit locally iii. Add your first formulas repository iv. Run the Hello Wor

ZUP IT INNOVATION 562 Nov 23, 2022
Go testing in the browser. Integrates with `go test`. Write behavioral tests in Go.

GoConvey is awesome Go testing Welcome to GoConvey, a yummy Go testing tool for gophers. Works with go test. Use it in the terminal or browser accordi

SmartyStreets 7.5k Nov 27, 2022
Go testing in the browser. Integrates with `go test`. Write behavioral tests in Go.

GoConvey is awesome Go testing Welcome to GoConvey, a yummy Go testing tool for gophers. Works with go test. Use it in the terminal or browser accordi

SmartyStreets 7.5k Nov 27, 2022
Selenium Hub successor running browsers within containers. Scalable, immutable, self hosted Selenium-Grid on any platform with single binary.

Selenoid Selenoid is a powerful implementation of Selenium hub using Docker containers to launch browsers. Features One-command Installation Start bro

Aerokube 2.3k Dec 2, 2022
fuzzer for a single http parameter which checks if the response does/does not contain a certain given string

single http parameter fuzzer DISCLAIMER: ONLY USE THIS PROGRAM ON TARGETS YOU HAVE PERMISSION TO FUZZ! Initially used as a "poor man's" http fuzzer fo

null 0 Dec 19, 2021
A Go library help testing your RESTful API application

RESTit A Go micro-framework to help writing RESTful API integration test Package RESTit provides helps to those who want to write an integration test

RESTit 55 Oct 28, 2022
Fortio load testing library, command line tool, advanced echo server and web UI in go (golang). Allows to specify a set query-per-second load and record latency histograms and other useful stats.

Fortio Fortio (Φορτίο) started as, and is, Istio's load testing tool and now graduated to be its own project. Fortio is also used by, among others, Me

Fortio (Φορτίο) 2.8k Nov 28, 2022
End-to-end HTTP and REST API testing for Go.

httpexpect Concise, declarative, and easy to use end-to-end HTTP and REST API testing for Go (golang). Basically, httpexpect is a set of chainable bui

Victor Gaydov 2k Dec 4, 2022
Lightweight service virtualization/API simulation tool for developers and testers

API simulations for development and testing Hoverfly is a lightweight, open source API simulation tool. Using Hoverfly, you can create realistic simul

null 1.9k Nov 21, 2022
This repository includes consumer driven contract test for provider, unit test and counter api.

This repository includes consumer driven contract test for provider, unit test and counter api.

Ahmet Zümberoğlu 0 Feb 1, 2022
A toolkit with common assertions and mocks that plays nicely with the standard library

Testify - Thou Shalt Write Tests ℹ️ We are working on testify v2 and would love to hear what you'd like to see in it, have your say here: https://cutt

Stretchr, Inc. 18.3k Nov 28, 2022
HTTP load testing tool and library. It's over 9000!

Vegeta Vegeta is a versatile HTTP load testing tool built out of a need to drill HTTP services with a constant request rate. It can be used both as a

Tomás Senart 20.5k Dec 4, 2022
A library for generating fake data such as names, addresses, and phone numbers.

faker Faker is a library for generating fake data such as names, addresses, and phone numbers. It is a (mostly) API-compatible port of Ruby Faker gem

Dmitri Goutnik 310 Dec 2, 2022
A WebDriver client and acceptance testing library for Go

Agouti Agouti is a library for writing browser-based acceptance tests in Google Go. It provides Gomega matchers and plays nicely with Ginkgo or Spec.

Stephen Levine 806 Nov 29, 2022
A simple and expressive HTTP server mocking library for end-to-end tests in Go.

mockhttp A simple and expressive HTTP server mocking library for end-to-end tests in Go. Installation go get -d github.com/americanas-go/mockhttp Exa

Americanas Go 6 Dec 19, 2021
Expressive end-to-end HTTP API testing made easy in Go

baloo Expressive and versatile end-to-end HTTP API testing made easy in Go (golang), built on top of gentleman HTTP client toolkit. Take a look to the

Tom 746 Nov 19, 2022