Help us shape the future of Go! Take the 2026 Go Developer Survey

chromedp

package module
v0.17.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 3, 2026 License: MIT Imports: 45 Imported by: 2,460

README

About chromedp

chromedp logo

Package chromedp drives browsers that speak the Chrome DevTools Protocol from Go. It needs no external driver.

Unit Tests Go Reference Releases Discord Discussion

Installing

Install the package with go get. The module needs Go 1.27 or newer. Version v0.17.0 uses the typed cdproto v0.157.3 and has the generic and iterator API. The earlier versions of cdproto, v0.157.0, v0.157.1 and v0.157.2, have the old API.

go get -u github.com/chromedp/chromedp

Usage

An action is a func that runs against a browser tab and returns a value. chromedp.Do runs actions that return nothing, and chromedp.Run runs one action and returns its value:

ctx, cancel := chromedp.NewContext(context.Background())
defer cancel()

if err := chromedp.Do(ctx, chromedp.Navigate(`https://pkg.go.dev/`)); err != nil {
	log.Fatal(err)
}
title, err := chromedp.Run(ctx, chromedp.Title())
if err != nil {
	log.Fatal(err)
}
fmt.Println(title)

A page event is an iterator. chromedp.Events subscribes when it returns, so a program can subscribe, trigger the event, and then read it:

loaded := chromedp.Events(ctx, page.LoadEventFired)
if err := chromedp.Do(ctx, chromedp.Navigate(`https://pkg.go.dev/`)); err != nil {
	log.Fatal(err)
}
for ev, err := range loaded {
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(ev.Timestamp)
	break
}

docs/API.md describes the API. It has 14 examples that show the old code and the new code side by side. docs/MIGRATION.md lists every renamed and removed name.

See the Go reference for the documentation and examples. The examples repository has more examples of complex actions and of other common tasks, such as full page screenshots.

Visible browser

By default, chromedp runs Chrome in headless mode, so no window opens. To see the browser, add WithVisibleWindow. Set the variable CHROMEDP_VISIBLEWINDOW=1 to get the same result with no change in the code. On Linux, a visible window needs DISPLAY or WAYLAND_DISPLAY. Without them, the first Run returns chromedp.ErrNoDisplay.

ctx, cancel := chromedp.NewContext(context.Background(), chromedp.WithVisibleWindow())
defer cancel()
chromedp.Do(ctx, chromedp.Navigate("https://example.com"))
chromedp.WaitClosed(ctx) // block until the user closes the window

To leave the browser open after the program ends, add WithKeepOpen. The program can print the address, and another program can attach to it with NewRemoteAllocator. The profile directory stays on disk, and you must delete it yourself.

ctx, _ := chromedp.NewContext(context.Background(), chromedp.WithVisibleWindow(), chromedp.WithKeepOpen())
chromedp.Do(ctx, chromedp.Navigate("https://example.com"))
wsURL, profile := chromedp.KeptOpen(ctx)
fmt.Println("attach to", wsURL, "profile", profile)
// The program ends here. The browser stays open.

Frequently Asked Questions

I cannot see any Chrome browser window

By default, chromedp runs Chrome in headless mode. See Visible browser. See also DefaultExecAllocatorOptions, and see an example that overrides the default options.

I see "context canceled" errors

When the connection to the browser is lost, chromedp cancels the context. This can cause the error. It happens, for example, when someone closes the browser by hand, or when something kills the browser process.

How does chromedp talk to the browser it starts?

By default, through a pipe. chromedp starts Chrome with --remote-debugging-pipe and uses two extra file descriptors, so Chrome opens no debugging port. To use a websocket and a debugging port instead, add the chromedp.WebSocket option to the exec allocator. A remote-debugging-port or remote-debugging-address flag also selects the websocket, and so does WithKeepOpen. On Windows chromedp always uses the websocket.

Chrome exits as soon as my Go program finishes

On Linux, chromedp kills the Chrome child processes that it started, so that no resources leak. To leave Chrome open, add chromedp.WithKeepOpen. See Visible browser. You can also start Chrome yourself and connect with RemoteAllocator.

Calling an action or a command results in "invalid context"

chromedp.Do, chromedp.Run and chromedp.Call need a context that came from chromedp.NewContext, because the context holds the browser and the tab. Any other context gives ErrInvalidContext.

How do I send a protocol command that has no action?

Call it with chromedp.Call, which runs the command on the tab of the context:

ctx, cancel := chromedp.NewContext(context.Background())
defer cancel()

res, err := chromedp.Call(ctx, page.GetFrameTree, cdp.Empty{})

Inside an action, call cdp.Call(ctx, t, command, params) with the target t that the action receives. The target is the tab of the context. The commands and their parameter structs are in github.com/chromedp/cdproto.

I have an action of the old kind

Wrap it with chromedp.Legacy. The old kind is a value with a Do(context.Context) error method.

I want to use chromedp on a headless environment

Run the Go program that uses chromedp inside the chromedp/headless-shell image. The image has headless-shell, a smaller headless build of Chrome. chromedp finds it by default.

Contributing

Read CONTRIBUTING.md before you send a change. AGENTS.md holds the rules for people and coding agents. The tests need Chrome or the headless-shell image.

These documents are in docs/:

Document Holds
docs/PLAN.md the purpose, the architecture and the open questions
docs/PROGRESS.md where the work stands
docs/BACKLOG.md known work that is not done
docs/API.md the new API, with old and new code side by side
docs/MIGRATION.md every renamed and removed name
docs/decisions/README.md the index of every recorded decision

Questions and ideas

Ask a question, or suggest a feature, in Discussions. The issue tracker is for bugs. You can also chat on Discord.

Resources

Documentation

Overview

Package chromedp is a high level Chrome DevTools Protocol client. It drives browsers to scrape web pages, to test them, and to profile them.

chromedp needs no external driver. It implements the asynchronous protocol in Go.

This package includes a number of simple examples. The module chromedp/examples has more complex examples.

Example (DocumentDump)
package main

import (
	"context"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/httptest"
	"strings"

	"github.com/chromedp/chromedp"
)

func writeHTML(content string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		io.WriteString(w, strings.TrimSpace(content))
	})
}

func main() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	ts := httptest.NewServer(writeHTML(`<!doctype html>
<html>
<body>
  <div id="content" style="display:block;">the content</div>
</body>
</html>`))
	defer ts.Close()

	const expr = `(function(d, id, v) {
		var b = d.querySelector('body');
		var el = d.createElement('div');
		el.id = id;
		el.innerText = v;
		b.insertBefore(el, b.childNodes[0]);
	})(document, %q, %q);`

	s := fmt.Sprintf(expr, "thing", "a new thing!")

	if err := chromedp.Do(ctx, chromedp.Navigate(ts.URL)); err != nil {
		log.Fatal(err)
	}
	nodes, err := chromedp.Run(ctx, chromedp.Nodes(chromedp.JSPath(`document`),
		chromedp.Populate(-1, true)))
	if err != nil {
		log.Fatal(err)
	}
	if err := chromedp.Do(ctx,
		chromedp.WaitVisible(`#content`),
		chromedp.Evaluate[chromedp.Void](s),
		chromedp.WaitVisible(`#thing`),
	); err != nil {
		log.Fatal(err)
	}

	fmt.Println("Document tree:")
	fmt.Print(nodes[0].Dump("  ", "  ", false))

}
Output:
Document tree:
  #document <Document>
    html <DocumentType>
    html
      head
      body
        div#thing
          #text "a new thing!"
        div#content [style="display:block;"]
          #text "the content"
Example (Dump)
package main

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/httptest"
	"strings"

	"github.com/chromedp/chromedp"
)

func writeHTML(content string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		io.WriteString(w, strings.TrimSpace(content))
	})
}

func main() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	ts := httptest.NewServer(writeHTML(`<!doctype html>
<html>
<body>
  <div id="content" style="display:block;">the content</div>
</body>
</html>`))
	defer ts.Close()

	const expr = `(function(d, id, v) {
		var b = d.querySelector('body');
		var el = d.createElement('div');
		el.id = id;
		el.innerText = v;
		b.insertBefore(el, b.childNodes[0]);
	})(document, %q, %q);`

	s := fmt.Sprintf(expr, "thing", "a new thing!")

	var buf bytes.Buffer
	if err := chromedp.Do(ctx,
		chromedp.Navigate(ts.URL),
		chromedp.WaitVisible(`#content`),
		chromedp.Evaluate[chromedp.Void](s),
		chromedp.WaitVisible(`#thing`),
		chromedp.Dump(chromedp.JSPath(`document`), &buf),
	); err != nil {
		log.Fatal(err)
	}

	fmt.Println("Document tree:")
	fmt.Print(buf.String())

}
Output:
Document tree:
#document <Document>
  html <DocumentType>
  html
    head
    body
      div#thing
        #text "a new thing!"
      div#content [style="display:block;"]
        #text "the content"
Example (RetrieveHTML)
package main

import (
	"context"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/httptest"
	"strings"

	"github.com/chromedp/chromedp"
)

func writeHTML(content string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		io.WriteString(w, strings.TrimSpace(content))
	})
}

func main() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	ts := httptest.NewServer(writeHTML(`
<body>
<p id="content" onclick="changeText()">Original content.</p>
<script>
function changeText() {
	document.getElementById("content").textContent = "New content!"
}
</script>
</body>
	`))
	defer ts.Close()

	if err := chromedp.Do(ctx, chromedp.Navigate(ts.URL)); err != nil {
		log.Fatal(err)
	}
	outerBefore, err := chromedp.Run(ctx, chromedp.OuterHTML(chromedp.CSS("#content")))
	if err != nil {
		log.Fatal(err)
	}
	if err := chromedp.Do(ctx, chromedp.Click(chromedp.CSS("#content"))); err != nil {
		log.Fatal(err)
	}
	outerAfter, err := chromedp.Run(ctx, chromedp.OuterHTML(chromedp.CSS("#content")))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("OuterHTML before clicking:")
	fmt.Println(outerBefore)
	fmt.Println("OuterHTML after clicking:")
	fmt.Println(outerAfter)

}
Output:
OuterHTML before clicking:
<p id="content" onclick="changeText()">Original content.</p>
OuterHTML after clicking:
<p id="content" onclick="changeText()">New content!</p>

Index

Examples

Constants

Mouse event types for MouseEvent.

View Source
const (
	ModifierNone    = kb.ModifierNone
	ModifierAlt     = kb.ModifierAlt
	ModifierCtrl    = kb.ModifierCtrl
	ModifierMeta    = kb.ModifierMeta
	ModifierShift   = kb.ModifierShift
	ModifierCommand = kb.ModifierCommand
)

Modifier values.

View Source
const (
	NodeTypeElement               = 1
	NodeTypeAttribute             = 2
	NodeTypeText                  = 3
	NodeTypeCDATA                 = 4
	NodeTypeEntityReference       = 5
	NodeTypeEntity                = 6
	NodeTypeProcessingInstruction = 7
	NodeTypeComment               = 8
	NodeTypeDocument              = 9
	NodeTypeDocumentType          = 10
	NodeTypeDocumentFragment      = 11
	NodeTypeNotation              = 12
)

NodeType values.

View Source
const EmptyFrameID = cdp.FrameID("")

EmptyFrameID is the "non-existent" frame id.

View Source
const EmptyNodeID = cdp.NodeID(0)

EmptyNodeID is the "non-existent" node id.

Variables

View Source
var (
	// DefaultUnmarshalOptions are default unmarshal options.
	DefaultUnmarshalOptions = jsonv2.JoinOptions(
		jsonv2.DefaultOptionsV2(),
		jsontext.AllowInvalidUTF8(true),
	)
	// DefaultMarshalOptions are default marshal options.
	DefaultMarshalOptions = jsonv2.JoinOptions(
		jsonv2.DefaultOptionsV2(),
		jsontext.AllowInvalidUTF8(true),
	)
)
View Source
var DefaultExecAllocatorOptions = [...]ExecAllocatorOption{
	NoFirstRun,
	NoDefaultBrowserCheck,
	Headless,

	Flag("disable-background-networking", true),
	Flag("enable-features", "NetworkService,NetworkServiceInProcess"),
	Flag("disable-background-timer-throttling", true),
	Flag("disable-backgrounding-occluded-windows", true),
	Flag("disable-breakpad", true),
	Flag("disable-client-side-phishing-detection", true),
	Flag("disable-default-apps", true),
	Flag("disable-dev-shm-usage", true),
	Flag("disable-extensions", true),
	Flag("disable-features", "site-per-process,Translate,BlinkGenPropertyTrees"),
	Flag("disable-hang-monitor", true),
	Flag("disable-ipc-flooding-protection", true),
	Flag("disable-popup-blocking", true),
	Flag("disable-prompt-on-repost", true),
	Flag("disable-renderer-backgrounding", true),
	Flag("disable-sync", true),
	Flag("force-color-profile", "srgb"),
	Flag("metrics-recording-only", true),
	Flag("safebrowsing-disable-auto-update", true),
	Flag("enable-automation", true),
	Flag("password-store", "basic"),
	Flag("use-mock-keychain", true),
}

DefaultExecAllocatorOptions are the ExecAllocator options that NewContext uses when the parent context has no allocator. Do not modify this global. Use NewExecAllocator instead. See ExampleExecAllocator.

The list runs the browser in headless mode. To get a visible window, add VisibleWindow to a copy of the list, or give WithVisibleWindow to NewContext.

Functions

func BrowserEvents added in v0.17.0

func BrowserEvents[E any](ctx context.Context, ev cdp.Event[E]) iter.Seq2[E, error]

BrowserEvents is like Events for the events of the browser, such as the events of the target domain. It replaces ListenBrowser.

func ButtonLeft

func ButtonLeft(p *input.DispatchMouseEventParams)

ButtonLeft is a mouse action option to set the button clicked as the left mouse button.

func ButtonMiddle

func ButtonMiddle(p *input.DispatchMouseEventParams)

ButtonMiddle is a mouse action option to set the button clicked as the middle mouse button.

func ButtonNone

func ButtonNone(p *input.DispatchMouseEventParams)

ButtonNone is a mouse action option to set the button clicked as none (used for mouse movements).

func ButtonRight

func ButtonRight(p *input.DispatchMouseEventParams)

ButtonRight is a mouse action option to set the button clicked as the right mouse button.

func Call added in v0.17.0

func Call[P, R any](ctx context.Context, cmd cdp.Command[P, R], params P) (R, error)

Call runs the protocol command with the params on the target of the chromedp context, and returns its result. As Run does, it starts the browser and opens the target when the context has none yet.

Use it where only the context is at hand, for example in code that runs under Legacy. An Action receives its target, and calls cdp.Call with it:

res, err := chromedp.Call(ctx, page.Navigate, page.NavigateParams{URL: urlstr})

It returns ErrInvalidContext when ctx is not a chromedp context.

Example
package main

import (
	"context"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/httptest"
	"strings"

	"github.com/chromedp/cdproto/cdp"
	"github.com/chromedp/cdproto/page"
	"github.com/chromedp/chromedp"
)

func writeHTML(content string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		io.WriteString(w, strings.TrimSpace(content))
	})
}

func main() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	ts := httptest.NewServer(writeHTML(`<title>called</title>`))
	defer ts.Close()

	// Any protocol command runs on the target of an action. The target is
	// a cdp.Session, so cdp.Call takes it as is.
	frameTree := func(ctx context.Context, t *chromedp.Target) (*page.FrameTree, error) {
		res, err := cdp.Call(ctx, t, page.GetFrameTree, cdp.Empty{})
		return res.FrameTree, err
	}

	if err := chromedp.Do(ctx, chromedp.Navigate(ts.URL)); err != nil {
		log.Fatal(err)
	}
	tree, err := chromedp.Run(ctx, frameTree)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(strings.TrimPrefix(tree.Frame.URL, ts.URL) == "/")

	// Outside an action, use chromedp.Call with the context.
	res, err := chromedp.Call(ctx, page.GetFrameTree, cdp.Empty{})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(res.FrameTree.Frame.ID == tree.Frame.ID)

}
Output:
true
true

func CallBrowser added in v0.17.0

func CallBrowser[P, R any](ctx context.Context, cmd cdp.Command[P, R], params P) (R, error)

CallBrowser runs the protocol command with the params on the browser of the chromedp context, and returns its result. Use it for the commands of the browser and target domains. As Run does, it starts the browser when the context has none yet.

It returns ErrInvalidContext when ctx is not a chromedp context.

func Cancel added in v0.2.0

func Cancel(ctx context.Context) error

Cancel cancels a chromedp context, waits until the context frees its resources, and returns any error that occurred.

If the context allocated a browser, Cancel closes the browser gracefully. To limit how long Cancel waits for the browser to close, give the context a timeout:

tctx, tcancel := context.WithTimeout(ctx, 10 * time.Second)
defer tcancel()
chromedp.Cancel(tctx)

A "defer cancel()" is enough in most cases. Use Cancel to close a browser gracefully, or to get the errors that occur during the cancellation.

func DisableGPU added in v0.2.0

func DisableGPU(a *ExecAllocator)

DisableGPU is the command line option to disable the GPU process.

The --disable-gpu option is a temporary workaround for a few bugs in headless mode. The references below say that it is no longer required:

But this issue says that it is still required in some cases:

Chromium 139 and later has no fallback to Swiftshader, unless you pass the --enable-unsafe-swiftshader option:

func Do added in v0.17.0

func Do(ctx context.Context, steps ...Action[Void]) error

Do runs the actions against the target of the context, in order. It stops at the first error. See Run for the rules about the context.

For example:

err := chromedp.Do(ctx,
	chromedp.Navigate("https://example.com"),
	chromedp.Click(chromedp.CSS("a")),
)

func EmulateLandscape added in v0.4.0

EmulateLandscape is an emulate viewport option to set the device viewport screen orientation in landscape primary mode and an angle of 90.

func EmulateMobile added in v0.4.0

EmulateMobile is an emulate viewport option to toggle the device viewport to display as a mobile device.

func EmulatePortrait added in v0.4.0

EmulatePortrait is an emulate viewport option to set the device viewport screen orientation in portrait primary mode and an angle of 0.

func EmulateTouch added in v0.4.0

EmulateTouch is an emulate viewport option to enable touch emulation.

func EvalAsValue

func EvalAsValue(p *runtime.EvaluateParams)

EvalAsValue is an evaluate option that makes the evaluation encode the result of the expression as a JSON-encoded value.

func EvalIgnoreExceptions

func EvalIgnoreExceptions(p *runtime.EvaluateParams)

EvalIgnoreExceptions is an evaluate option that makes the evaluation ignore exceptions.

func EvalWithCommandLineAPI

func EvalWithCommandLineAPI(p *runtime.EvaluateParams)

EvalWithCommandLineAPI is an evaluate option that makes the DevTools Command Line API available to the evaluated script.

See Evaluate for how evaluate actions work.

Note: do not use this with untrusted JavaScript.

func Events added in v0.17.0

func Events[E any](ctx context.Context, ev cdp.Event[E]) iter.Seq2[E, error]

Events subscribes to the event on the target of the context, and returns an iterator over its payloads. It replaces ListenTarget.

The subscription starts when Events returns, and not when the caller starts to range. A caller can subscribe, trigger the event, and then range, so that no event is lost:

events := chromedp.Events(ctx, page.LoadEventFired)
if err := chromedp.Do(ctx, chromedp.Navigate(url)); err != nil {
	return err
}
for ev, err := range events {
	...
}

As Run does, Events starts the browser and opens the target when the context has none yet. If that fails, the iterator yields the error. See cdp.Events for the rules about ending the iteration. A caller must range over the iterator or cancel the context, because an iterator that nobody reads holds its subscription.

Example (AcceptAlert)
package main

import (
	"context"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/httptest"
	"strings"

	"github.com/chromedp/cdproto/page"
	"github.com/chromedp/chromedp"
)

func writeHTML(content string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		io.WriteString(w, strings.TrimSpace(content))
	})
}

func main() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	ts := httptest.NewServer(writeHTML(`
<input id='alert' type='button' value='alert' onclick='alert("alert text");'/>
	`))
	defer ts.Close()

	// The page waits for the dialog, and so does the Click below. A second
	// goroutine closes the dialog.
	dialogs := chromedp.Events(ctx, page.JavascriptDialogOpening)
	go func() {
		for ev, err := range dialogs {
			if err != nil {
				return
			}
			fmt.Println("closing alert:", ev.Message)
			_, err := chromedp.Call(ctx, page.HandleJavaScriptDialog, page.HandleJavaScriptDialogParams{Accept: true})
			if err != nil {
				log.Fatal(err)
			}
		}
	}()

	if err := chromedp.Do(ctx,
		chromedp.Navigate(ts.URL),
		chromedp.Click(chromedp.ID("alert")),
	); err != nil {
		log.Fatal(err)
	}

}
Output:
closing alert: alert text
Example (ConsoleLog)
package main

import (
	"context"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/httptest"
	"strings"

	"github.com/chromedp/cdproto/runtime"
	"github.com/chromedp/chromedp"
)

func writeHTML(content string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		io.WriteString(w, strings.TrimSpace(content))
	})
}

func main() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	ts := httptest.NewServer(writeHTML(`
<body>
<script>
	console.log("hello js world")
	console.warn("scary warning", 123)
	null.throwsException
</script>
</body>
	`))
	defer ts.Close()

	// Subscribe first. The subscriptions buffer the events, so the loops
	// below see the events of the navigation although they start later.
	console := chromedp.Events(ctx, runtime.ConsoleAPICalled)
	exceptions := chromedp.Events(ctx, runtime.ExceptionThrown)

	if err := chromedp.Do(ctx, chromedp.Navigate(ts.URL)); err != nil {
		log.Fatal(err)
	}

	calls := 0
	for ev, err := range console {
		if err != nil {
			log.Fatal(err)
		}
		fmt.Printf("* console.%s call:\n", ev.Type)
		for _, arg := range ev.Args {
			fmt.Printf("%s - %s\n", arg.Type, arg.Value)
		}
		if calls++; calls == 2 {
			break
		}
	}
	for ev, err := range exceptions {
		if err != nil {
			log.Fatal(err)
		}
		// Since ts.URL uses a random port, replace it.
		s := (&chromedp.ExceptionError{ExceptionDetails: ev.ExceptionDetails}).Error()
		s = strings.ReplaceAll(s, ts.URL, "<server>")
		// V8 changed the error messages for property access on null/undefined in version 9.3.310.
		// see: https://chromium.googlesource.com/v8/v8/+/c0fd89c3c089e888c4f4e8582e56db7066fa779b
		//      https://github.com/chromium/chromium/commit/1735cbf94c98c70ff7554a1e9e01bb9a4f91beb6
		// The test normalizes the message to stay compatible with the versions before this change.
		s = strings.ReplaceAll(s, "Cannot read property 'throwsException' of null", "Cannot read properties of null (reading 'throwsException')")
		fmt.Printf("* %s\n", s)
		break
	}

}
Output:
* console.log call:
string - "hello js world"
* console.warning call:
string - "scary warning"
number - 123
* exception "Uncaught" (4:6): TypeError: Cannot read properties of null (reading 'throwsException')
    at <server>/:5:7
Example (Network)
package main

import (
	"context"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/httptest"
	"strings"

	"github.com/chromedp/cdproto/network"
	"github.com/chromedp/chromedp"
)

func writeHTML(content string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		io.WriteString(w, strings.TrimSpace(content))
	})
}

func main() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	// The page has an image that does not exist.
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.URL.Path != "/" {
			http.NotFound(w, r)
			return
		}
		writeHTML(`<body><img src="/missing.png"/></body>`).ServeHTTP(w, r)
	}))
	defer ts.Close()

	// Subscribe before the navigation. The loop below can start after it.
	responses := chromedp.Events(ctx, network.ResponseReceived)

	if err := chromedp.Do(ctx, chromedp.Navigate(ts.URL)); err != nil {
		log.Fatal(err)
	}
	for ev, err := range responses {
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(strings.TrimPrefix(ev.Response.URL, ts.URL), ev.Response.Status)
		if ev.Type == network.ResourceTypeImage {
			break
		}
	}

}
Output:
/ 200
/missing.png 404

func Headless added in v0.2.0

func Headless(a *ExecAllocator)

Headless is the command line option to run in headless mode. It sets the headless flag, hides scrollbars, and mutes audio.

func IgnoreCertErrors added in v0.7.4

func IgnoreCertErrors(a *ExecAllocator)

IgnoreCertErrors is the command line option to ignore certificate errors. Use it to access an HTTPS website through a proxy.

func KeepOpen added in v0.17.0

func KeepOpen(a *ExecAllocator)

KeepOpen is an ExecAllocatorOption that leaves the browser open when the Go program ends or when the context is canceled. Use it to look at the page after the program is done. See also WithKeepOpen, KeptOpen and VisibleWindow.

The browser must outlive the program, so KeepOpen changes how the allocator starts it:

  • The allocator uses the websocket and not the pipe, because the pipe closes when the Go process exits, and Chrome then exits too. It starts Chrome with --remote-debugging-port=0 and reads the address from the file DevToolsActivePort in the user data directory. NewRemoteAllocator can connect to that address later.
  • The process starts detached: in a new session on Unix, and detached from the console and in a new process group on Windows. A func from ModifyCmdFunc runs first, and the detach settings come after it.
  • The allocator does not kill the process when the context ends. It waits for the process in a goroutine, so that no zombie process stays while the program runs.
  • The allocator never removes the user data directory. Unless you set UserDataDir, the directory is "keepopen-PID" in the directory "chromedp" of os.UserCacheDir, where PID is the process ID of the Go program. Each program run leaves one such directory, and you must remove it yourself. Two browsers of one program share the directory, so set UserDataDir when a program keeps more than one browser open.
  • Cancel does not close the browser. The output of the browser goes nowhere, so CombinedOutput has no effect. The library prints nothing. KeptOpen returns the address and the directory, so that the program can print them.

To close a kept browser, close its window, or kill its process. The process is available as Process of the Browser.

func KeptOpen added in v0.17.0

func KeptOpen(ctx context.Context) (wsURL, userDataDir string)

KeptOpen returns the websocket address of the browser of the context and the user data directory of the browser, so that a program can print them. Another program can attach to the address with NewRemoteAllocator. The user can delete the directory when the browser is closed.

KeptOpen returns two empty strings when the context has no browser yet, or when the allocator did not start the browser with KeepOpen. The browser starts at the first Run, so call KeptOpen after it.

Example

This example attaches to a browser that an earlier program left open.

package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/chromedp/chromedp"
)

func main() {
	wsURL := os.Args[1] // the address that the earlier program printed

	allocCtx, cancel := chromedp.NewRemoteAllocator(context.Background(), wsURL)
	defer cancel()
	ctx, cancel := chromedp.NewContext(allocCtx)
	defer cancel()

	title, err := chromedp.Run(ctx, chromedp.Title())
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(title)
}

func NewContext added in v0.2.0

func NewContext(parent context.Context, opts ...ContextOption) (context.Context, context.CancelFunc)

NewContext creates a chromedp context from the parent context. The context inherits the Allocator of the parent. By default, that is an ExecAllocator with DefaultExecAllocatorOptions.

If the parent context holds an allocated Browser, the child context inherits it, and its first Run creates a new tab on that browser. Otherwise, its first Run allocates a new browser.

Canceling the returned context closes a tab or a whole browser, as the rules above describe. To cancel a context and read the errors, see Cancel.

NewContext does not allocate or start a browser. That happens the first time that you call Run on the context.

Example (ManyTabs)
package main

import (
	"context"
	"fmt"
	"log"

	"github.com/chromedp/chromedp"
)

func main() {
	// new browser, first tab
	ctx1, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	// make sure that the first tab is created
	if err := chromedp.Do(ctx1); err != nil {
		log.Fatal(err)
	}

	// same browser, second tab
	ctx2, _ := chromedp.NewContext(ctx1)

	// make sure that the second tab is created
	if err := chromedp.Do(ctx2); err != nil {
		log.Fatal(err)
	}

	c1 := chromedp.FromContext(ctx1)
	c2 := chromedp.FromContext(ctx2)

	fmt.Printf("Same browser: %t\n", c1.Browser == c2.Browser)
	fmt.Printf("Same tab: %t\n", c1.Target == c2.Target)

}
Output:
Same browser: true
Same tab: false
Example (ReuseBrowser)
package main

import (
	"context"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/httptest"
	"strings"
	"time"

	"github.com/chromedp/chromedp"
)

func writeHTML(content string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		io.WriteString(w, strings.TrimSpace(content))
	})
}

func main() {
	ts := httptest.NewServer(writeHTML(`
<body>
<script>
	// Show the current cookies.
	var p = document.createElement("p")
	p.innerText = document.cookie
	p.setAttribute("id", "cookies")
	document.body.appendChild(p)

	// Override the cookies.
	document.cookie = "foo=bar"
</script>
</body>
	`))
	defer ts.Close()

	// create a new browser
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	// start the browser without a timeout
	if err := chromedp.Do(ctx); err != nil {
		log.Fatal(err)
	}

	for i := range 2 {
		func() {
			ctx, cancel := context.WithTimeout(ctx, time.Second)
			defer cancel()
			ctx, cancel = chromedp.NewContext(ctx)
			defer cancel()
			if err := chromedp.Do(ctx, chromedp.Navigate(ts.URL)); err != nil {
				log.Fatal(err)
			}
			cookies, err := chromedp.Run(ctx, chromedp.Text("#cookies"))
			if err != nil {
				log.Fatal(err)
			}
			fmt.Printf("Cookies at i=%d: %q\n", i, cookies)
		}()
	}

}
Output:
Cookies at i=0: ""
Cookies at i=1: "foo=bar"

func NewExecAllocator added in v0.2.0

func NewExecAllocator(parent context.Context, opts ...ExecAllocatorOption) (context.Context, context.CancelFunc)

NewExecAllocator creates a new context with an ExecAllocator. Use it with NewContext.

func NewRemoteAllocator added in v0.2.0

func NewRemoteAllocator(parent context.Context, url string, opts ...RemoteAllocatorOption) (context.Context, context.CancelFunc)

NewRemoteAllocator creates a new context with a RemoteAllocator. Use it with NewContext. The url must point to the websocket address of the browser, such as "ws://127.0.0.1:$PORT/devtools/browser/...".

If the url does not contain "/devtools/browser/", NewRemoteAllocator tries to find the correct url. It sends a request to "http://$HOST:$PORT/json/version".

NewRemoteAllocator accepts urls of these formats:

It does not accept "ws://127.0.0.1:9222/devtools/browser/", because the allocator does not try to modify it and it is invalid.

Use NoModifyURL to stop NewRemoteAllocator from changing the url.

func NoDefaultBrowserCheck added in v0.2.0

func NoDefaultBrowserCheck(a *ExecAllocator)

NoDefaultBrowserCheck is the Chrome command line option to disable the default browser check.

func NoFirstRun added in v0.2.0

func NoFirstRun(a *ExecAllocator)

NoFirstRun is the Chrome command line option to disable the first run dialog.

func NoModifyURL added in v0.8.7

func NoModifyURL(a *RemoteAllocator)

NoModifyURL is a RemoteAllocatorOption that prevents the remote allocator from modifying the websocket debugger URL passed to it.

func NoSandbox added in v0.2.0

func NoSandbox(a *ExecAllocator)

NoSandbox is the Chrome command line option to disable the sandbox.

func NodeEnabled

func NodeEnabled(s *Selector)

NodeEnabled is an element query option that waits until the browser has sent all queried element nodes. The nodes must be enabled (that is, they have no 'disabled' attribute).

func NodeNotPresent

func NodeNotPresent(s *Selector)

NodeNotPresent is an element query option that waits until no element matches the query.

Note: it sets the expected number of element nodes to 0.

func NodeNotVisible

func NodeNotVisible(s *Selector)

NodeNotVisible is an element query option that waits until the browser has sent all queried element nodes and they are not visible.

func NodeReady

func NodeReady(s *Selector)

NodeReady is an element query option that waits until the browser has sent all queried element nodes.

func NodeSelected

func NodeSelected(s *Selector)

NodeSelected is an element query option that waits until the browser has sent all queried element nodes. The nodes must be selected (that is, they have a 'selected' attribute).

func NodeVisible

func NodeVisible(s *Selector)

NodeVisible is an element query option that waits until the browser has sent all queried element nodes and they are visible.

func Run added in v0.2.0

func Run[T any](ctx context.Context, a Action[T]) (T, error)

Run runs the action against the target of the context, and returns its value. The context must be a chromedp context, typically made with NewContext.

The first time that you call Run on a context, Run allocates a browser with the Allocator. Do not set a timeout on the context of that first call, because the timeout stops the whole browser.

For example:

title, err := chromedp.Run(ctx, chromedp.Title())

Use Do to run several actions that return no value.

func RunResponse added in v0.5.4

func RunResponse(ctx context.Context, steps ...Action[Void]) (*network.Response, error)

RunResponse is an alternative to Do for a list of actions that trigger a page navigation, such as a click on a link or a button.

RunResponse runs the actions and blocks until a page loads. Then it returns the HTTP response of the HTML document. Use it to wait for the page, or to catch 404 status codes.

If the actions trigger several navigations, RunResponse uses only the first. If the actions trigger no navigation, RunResponse blocks until the context is canceled.

Example
package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"net/http/httptest"

	"github.com/chromedp/chromedp"
)

func main() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	// This server shows the URL path as the page title, and contains
	// a link that points to /foo.
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		fmt.Fprintf(w, `
			<head><title>%s</title></head>
			<body><a id="foo" href="/foo">foo</a></body>
		`, r.URL.Path)
	}))
	defer ts.Close()

	// The Navigate action already waits until a page loads, so Title runs
	// once the page is ready.
	if err := chromedp.Do(ctx, chromedp.Navigate(ts.URL)); err != nil {
		log.Fatal(err)
	}
	firstTitle, err := chromedp.Run(ctx, chromedp.Title())
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("first title:", firstTitle)

	// However, actions like Click do not always trigger a page navigation,
	// so they do not wait for a page load directly. Wrapping them with
	// RunResponse does that waiting, and also obtains the HTTP response.
	resp, err := chromedp.RunResponse(ctx, chromedp.Click(chromedp.ID("foo")))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("second status code:", resp.Status)

	// Getting the title again works, because the page finished loading once
	// more.
	secondTitle, err := chromedp.Run(ctx, chromedp.Title())
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("second title:", secondTitle)

	// You can also wrap Navigate with RunResponse to get the response
	// information for that case too.
	resp, err = chromedp.RunResponse(ctx, chromedp.Navigate(ts.URL+"/bar"))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("third status code:", resp.Status)

	// NavigateResponse is a shorter way to do the same.
	resp, err = chromedp.Run(ctx, chromedp.NavigateResponse(ts.URL+"/baz"))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("fourth status code:", resp.Status)

}
Output:
first title: /
second status code: 200
second title: /foo
third status code: 200
fourth status code: 200

func Targets added in v0.2.0

func Targets(ctx context.Context) ([]*target.Info, error)

Targets lists the targets of the browser of the context.

func VisibleWindow added in v0.17.0

func VisibleWindow(a *ExecAllocator)

VisibleWindow is the command line option to run the browser with a visible window. It removes the flags that make the browser quiet or hidden, and it starts the window maximized.

It removes these flags: headless, hide-scrollbars, mute-audio, enable-automation (the infobar that says that software controls the browser) and disable-extensions. It keeps every other flag, and it adds start-maximized. It does not open the developer tools. To open them for every tab, add Flag("auto-open-devtools-for-tabs", true).

Add VisibleWindow after the options that it must change. It only removes the flags that exist when it runs. For example:

opts := append(chromedp.DefaultExecAllocatorOptions[:], chromedp.VisibleWindow)
ctx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)

On Linux, Allocate returns ErrNoDisplay when the environment variables DISPLAY and WAYLAND_DISPLAY are both empty. The allocator never falls back to headless mode. Allocate does no such check on macOS and Windows.

Example

This example shows the allocator options. They work with NewExecAllocator, when the program makes its own allocator.

package main

import (
	"context"
	"log"

	"github.com/chromedp/chromedp"
)

func main() {
	opts := append(chromedp.DefaultExecAllocatorOptions[:],
		chromedp.VisibleWindow,
		chromedp.Flag("auto-open-devtools-for-tabs", true),
	)
	allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
	defer cancel()
	ctx, cancel := chromedp.NewContext(allocCtx)
	defer cancel()

	if err := chromedp.Do(ctx, chromedp.Navigate("https://example.com")); err != nil {
		log.Fatal(err)
	}
	chromedp.WaitClosed(ctx)
}

func WaitClosed added in v0.17.0

func WaitClosed(ctx context.Context) error

WaitClosed blocks until the browser process of the context exits, for example when the user closes the last window, or until ctx ends. It returns nil when the process exited, and the error of ctx otherwise. Use it in a program that must stay alive while the user looks at the window.

If the context has no browser yet, WaitClosed starts one, as Run does. For a browser that a RemoteAllocator reaches, WaitClosed waits until the connection drops, because there is no process to watch.

func WaitNewTarget added in v0.4.0

func WaitNewTarget(ctx context.Context, fn func(*target.Info) bool) <-chan target.ID

WaitNewTarget waits for the current target to open a new target. When fn matches a new target that is not attached, WaitNewTarget sends its target ID on the returned channel. The channel closes without a value when the context has no valid target.

Example
package main

import (
	"context"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/httptest"
	"strings"

	"github.com/chromedp/cdproto/target"
	"github.com/chromedp/chromedp"
)

func writeHTML(content string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		io.WriteString(w, strings.TrimSpace(content))
	})
}

func main() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	mux := http.NewServeMux()
	mux.Handle("/first", writeHTML(`
<input id='newtab' type='button' value='open' onclick='window.open("/second", "_blank");'/>
	`))
	mux.Handle("/second", writeHTML(``))
	ts := httptest.NewServer(mux)
	defer ts.Close()

	// Grab the first spawned tab that is not blank.
	ch := chromedp.WaitNewTarget(ctx, func(info *target.Info) bool {
		return info.URL != ""
	})
	if err := chromedp.Do(ctx,
		chromedp.Navigate(ts.URL+"/first"),
		chromedp.Click(chromedp.ID("newtab")),
	); err != nil {
		log.Fatal(err)
	}
	newCtx, cancel := chromedp.NewContext(ctx, chromedp.WithTargetID(<-ch))
	defer cancel()

	urlstr, err := chromedp.Run(newCtx, chromedp.Location())
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("new tab's path:", strings.TrimPrefix(urlstr, ts.URL))

}
Output:
new tab's path: /second

func WebSocket added in v0.17.0

func WebSocket(a *ExecAllocator)

WebSocket is an ExecAllocatorOption that makes the allocator connect to the browser with a websocket, as chromedp did before. The default is a pipe: the allocator starts the browser with --remote-debugging-pipe, and the browser reads the commands from the file descriptor 3 and writes the responses and the events to the file descriptor 4. A pipe needs no port.

Use WebSocket when the browser must open a debugging port, for example to let a second program connect to it. The Flag options "remote-debugging-port" and "remote-debugging-address" also select the websocket. On Windows the allocator always uses the websocket, because os/exec cannot pass extra file descriptors there.

Types

type Action

type Action[T any] func(ctx context.Context, t *Target) (T, error)

Action is a step that runs against the target of a chromedp context and returns a value of the type T. An action that returns no value has the type Action[Void].

An action is a plain func, so a program can write its own:

title := func(ctx context.Context, t *chromedp.Target) (string, error) {
	res, err := cdp.Call(ctx, t, runtime.Evaluate, runtime.EvaluateParams{
		Expression:    "document.title",
		ReturnByValue: new(true),
	})
	...
}

The target t is a cdp.Session. Use it with cdp.Call to send a protocol command, and with cdp.Events to receive protocol events.

func AttributeValue

func AttributeValue[S Selectable](sel S, name string, opts ...QueryOption) Action[AttributeResult]

AttributeValue is an element query action that retrieves the element attribute value for the first element node matching the selector. The result tells whether the attribute exists.

func Attributes

func Attributes[S Selectable](sel S, opts ...QueryOption) Action[map[string]string]

Attributes is an element query action that retrieves the element attributes for the first element node matching the selector.

func AttributesAll

func AttributesAll[S Selectable](sel S, opts ...QueryOption) Action[[]map[string]string]

AttributesAll is an element query action that retrieves the element attributes for all element nodes matching the selector. Note: use it with a CSSAll selector.

func Blur

func Blur[S Selectable](sel S, opts ...QueryOption) Action[Void]

Blur is an element query action that unfocuses (blurs) the first element node matching the selector.

func CallFunctionOn added in v0.7.4

func CallFunctionOn[T any](functionDeclaration string, opt CallOption, args ...any) Action[T]

CallFunctionOn is an action that calls a JavaScript function and decodes the result of the function into the type T.

T is handled as in Evaluate.

Do not set these fields of runtime.CallFunctionOnParams:

  • ReturnByValue: CallFunctionOn sets it from the type T.
  • Arguments: pass the arguments with args instead.

If the function throws an exception, CallFunctionOn returns it as an error.

func CaptureScreenshot

func CaptureScreenshot() Action[[]byte]

CaptureScreenshot is an action that takes a screenshot of the current browser viewport.

It acts like the command "Capture screenshot" in Chrome. See the behavior notes of Screenshot for more information.

To take a screenshot of one element, use the Screenshot action.

For an example that takes a screenshot of the entire page, see screenshot.

func Clear

func Clear[S Selectable](sel S, opts ...QueryOption) Action[Void]

Clear is an element query action that clears the values of any input/textarea element nodes matching the selector.

func Click

func Click[S Selectable](sel S, opts ...QueryOption) Action[Void]

Click is an element query action that sends a mouse click event to the first element node matching the selector.

Example
package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"net/http/httptest"

	"github.com/chromedp/cdproto/page"
	"github.com/chromedp/chromedp"
)

func main() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		fmt.Fprintf(w, `<head><title>%s</title></head><body><a id="next" href="/next">next</a></body>`, r.URL.Path)
	}))
	defer ts.Close()

	// Click does not wait for a page load. So WaitEvent subscribes to the
	// load event first, then runs the click, and returns the first event
	// that comes after it. No event is lost between the click and the wait.
	if err := chromedp.Do(ctx, chromedp.Navigate(ts.URL)); err != nil {
		log.Fatal(err)
	}
	_, err := chromedp.Run(ctx, chromedp.WaitEvent(page.LoadEventFired, nil,
		chromedp.Click(chromedp.ID("next"))))
	if err != nil {
		log.Fatal(err)
	}
	title, err := chromedp.Run(ctx, chromedp.Title())
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("title after the click:", title)

}
Output:
title after the click: /next

func ComputedStyle

func ComputedStyle[S Selectable](sel S, opts ...QueryOption) Action[[]*css.ComputedStyleProperty]

ComputedStyle is an element query action that retrieves the computed style of the first element node matching the selector.

func Dimensions

func Dimensions[S Selectable](sel S, opts ...QueryOption) Action[*dom.BoxModel]

Dimensions is an element query action that retrieves the box model dimensions for the first element node matching the selector.

func DoubleClick

func DoubleClick[S Selectable](sel S, opts ...QueryOption) Action[Void]

DoubleClick is an element query action that sends a mouse double click event to the first element node matching the selector.

func Dump added in v0.9.5

func Dump[S Selectable](sel S, w io.Writer, opts ...QueryOption) Action[Void]

Dump is an element query action that writes a readable tree of the first element node matching the selector and its children. The tree ends at the specified depth.

See DumpTo for more options, which include the sleep wait timeout.

func DumpTo added in v0.9.5

func DumpTo[S Selectable](sel S, w io.Writer, prefix, indent string, nodeIDs bool, depth int64, pierce bool, wait time.Duration, opts ...QueryOption) Action[Void]

DumpTo is an element query action that writes a readable tree of the first element node matching the selector and its children. The tree ends at the specified depth.

See Dump for a simpler interface.

func Emulate added in v0.4.0

func Emulate(device Device) Action[Void]

Emulate is an action to emulate a specific device.

See device for a set of ready-made devices and modes.

Example
package main

import (
	"context"
	"log"
	"os"

	"github.com/chromedp/chromedp"
	"github.com/chromedp/chromedp/device"
)

func main() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	if err := chromedp.Do(ctx,
		chromedp.Emulate(device.IPhone7),
		chromedp.Navigate(`https://duckduckgo.com/`),
		chromedp.SendKeys(`textarea[name=q]`, "what's my user agent?\n"),
		chromedp.WaitVisible(chromedp.ID(`zci-answer`)),
	); err != nil {
		log.Fatal(err)
	}
	buf, err := chromedp.Run(ctx, chromedp.CaptureScreenshot())
	if err != nil {
		log.Fatal(err)
	}

	if err := os.WriteFile("iphone7-ua.png", buf, 0o644); err != nil {
		log.Fatal(err)
	}

	// This example uses a live website and writes a file, so it has no
	// Output comment: go test builds it and does not run it. A live website
	// can change or be slow, and the example made the tests fail on CI.
}

func EmulateReset added in v0.4.0

func EmulateReset() Action[Void]

EmulateReset is an action that resets the device emulation.

It resets the viewport, the screen orientation, the user agent, and the mobile and touch emulation. The new values are the original values from the start of the browser.

func EmulateViewport added in v0.4.0

func EmulateViewport(width, height int64, opts ...EmulateViewportOption) Action[Void]

EmulateViewport is an action that changes the browser viewport.

It wraps calls to emulation.SetDeviceMetricsOverride and emulation.SetTouchEmulationEnabled.

Note: by default, this action sets the screen orientation to landscape and disables mobile and touch emulation. To change that, use the emulate viewport options EmulateOrientation (or EmulateLandscape or EmulatePortrait), EmulateMobile, and EmulateTouch.

func Evaluate

func Evaluate[T any](expression string, opts ...EvaluateOption) Action[T]

Evaluate is an action that evaluates the JavaScript expression and decodes the result of the script into the type T.

When T is Void, Evaluate ignores the script result.

When T is []byte, the result is the raw JSON-encoded value of the script result.

When T is *runtime.RemoteObject, the result is the low-level protocol type, and Evaluate does not convert it. The original objects can stay in memory until the page navigates or closes. Use `runtime.ReleaseObject` or `runtime.ReleaseObjectGroup` to ask the browser to release them.

For all other types, the script returns the result "by value" (that is, JSON-encoded). Evaluate then decodes it into a value of type T. Only a chan, func, interface, map, pointer, or slice type can be nil. When the script result is "undefined" or "null" and T cannot be nil, the action returns ErrJSUndefined or ErrJSNull respectively.

For example:

n, err := chromedp.Run(ctx, chromedp.Evaluate[int](`1 + 2`))
Example
package main

import (
	"context"
	"fmt"
	"log"

	"github.com/chromedp/cdproto/runtime"
	"github.com/chromedp/chromedp"
)

func main() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	// Ignore the result:
	{
		if err := chromedp.Do(ctx, chromedp.Evaluate[chromedp.Void](`window.scrollTo(0, 100)`)); err != nil {
			log.Fatal(err)
		}
	}

	// Receive a primary value:
	{
		sum, err := chromedp.Run(ctx, chromedp.Evaluate[int](`1+2`))
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(sum)
	}

	// ErrJSUndefined:
	{
		if _, err := chromedp.Run(ctx, chromedp.Evaluate[int](`undefined`)); err != nil {
			fmt.Println(err)
		}
	}

	// ErrJSNull:
	{
		if _, err := chromedp.Run(ctx, chromedp.Evaluate[int](`null`)); err != nil {
			fmt.Println(err)
		}
	}

	// Accept undefined/null result:
	{
		val, err := chromedp.Run(ctx, chromedp.Evaluate[*int](`undefined`))
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(val)
	}

	// Receive an array value:
	{
		val, err := chromedp.Run(ctx, chromedp.Evaluate[[]int](`[1,2]`))
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(val)
	}

	// Map and Slice accept undefined/null:
	{
		val, err := chromedp.Run(ctx, chromedp.Evaluate[[]int](`null`))
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println("slice is nil:", val == nil)
	}

	// Receive the raw bytes:
	{
		buf, err := chromedp.Run(ctx, chromedp.Evaluate[[]byte](`alert`))
		if err != nil {
			log.Fatal(err)
		}
		fmt.Printf("%s\n", buf)
	}

	// Receive the RemoteObject:
	{
		res, err := chromedp.Run(ctx, chromedp.Evaluate[*runtime.RemoteObject](`alert`))
		if err != nil {
			log.Fatal(err)
		}
		if res.ObjectID != "" {
			fmt.Println("objectId is present")
		}
	}

}
Output:
3
encountered an undefined value
<nil>
[1 2]
slice is nil: true
{}
objectId is present

func EvaluateAsDevTools

func EvaluateAsDevTools[T any](expression string, opts ...EvaluateOption) Action[T]

EvaluateAsDevTools is an action that evaluates a JavaScript expression as Chrome DevTools does. It evaluates the expression in the "console" context and makes the Command Line API available to the script.

See Evaluate for how the expressions are evaluated.

Note: do not use this with untrusted JavaScript.

func Focus

func Focus[S Selectable](sel S, opts ...QueryOption) Action[Void]

Focus is an element query action that focuses the first element node matching the selector.

func FullScreenshot added in v0.7.0

func FullScreenshot(quality int) Action[[]byte]

FullScreenshot takes a full screenshot of the entire browser viewport, with the given image quality.

It acts like the command "Capture full size screenshot" in Chrome. See the behavior notes of Screenshot for more information.

The valid range of the compression quality is [0..100]. When the quality is 100, the image format is png. Otherwise the image format is jpeg.

Example
package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/chromedp/chromedp"
)

func main() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	if err := chromedp.Do(ctx, chromedp.Navigate(`https://google.com`)); err != nil {
		log.Fatal(err)
	}
	buf, err := chromedp.Run(ctx, chromedp.FullScreenshot(90))
	if err != nil {
		log.Fatal(err)
	}

	if err := os.WriteFile("fullScreenshot.jpeg", buf, 0o644); err != nil {
		log.Fatal(err)
	}
	fmt.Println("wrote fullScreenshot.jpeg")
}
Output:
wrote fullScreenshot.jpeg

func Func added in v0.17.0

func Func(f func(ctx context.Context, t *Target) error) Action[Void]

Func makes an action that returns no value from a func that returns only an error.

func InnerHTML

func InnerHTML[S Selectable](sel S, opts ...QueryOption) Action[string]

InnerHTML is an element query action that retrieves the inner html of the first element node matching the selector.

func JavascriptAttribute

func JavascriptAttribute[T any, S Selectable](sel S, name string, opts ...QueryOption) Action[T]

JavascriptAttribute is an element query action that retrieves the JavaScript attribute for the first element node matching the selector. It decodes the attribute into the type T, as Evaluate does.

func KeyEvent added in v0.4.0

func KeyEvent(keys string, opts ...KeyOption) Action[Void]

KeyEvent is a key action that synthesizes a keyDown, char, and keyUp event for each rune in keys, with any key options.

Only well-known, "printable" characters get char events.

See the SendKeys action to synthesize key events for a specific element node.

See the kb package for implementation details and a list of well-known keys.

func KeyEventNode added in v0.4.0

func KeyEventNode(n *Node, keys string, opts ...KeyOption) Action[Void]

KeyEventNode is a key action that dispatches a key event on an element node.

func Legacy added in v0.17.0

func Legacy(a OldAction) Action[Void]

Legacy makes an action from an action of the previous version. The old action receives the same context, so Call and CallBrowser work inside it.

Example
package main

import (
	"context"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/httptest"
	"strings"

	"github.com/chromedp/cdproto/runtime"
	"github.com/chromedp/chromedp"
)

func writeHTML(content string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		io.WriteString(w, strings.TrimSpace(content))
	})
}

// oldTitle is an action of the previous version of chromedp. It has a Do
// method.
type oldTitle struct{ res *string }

func (a oldTitle) Do(ctx context.Context) error {
	res, err := chromedp.Call(ctx, runtime.Evaluate, runtime.EvaluateParams{
		Expression:    "document.title",
		ReturnByValue: new(true),
	})
	if err != nil {
		return err
	}
	return json.Unmarshal(res.Result.Value, a.res)
}

func main() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	ts := httptest.NewServer(writeHTML(`<title>old action</title>`))
	defer ts.Close()

	var title string
	if err := chromedp.Do(ctx,
		chromedp.Navigate(ts.URL),
		chromedp.Legacy(oldTitle{&title}),
	); err != nil {
		log.Fatal(err)
	}
	fmt.Println(title)

}
Output:
old action

func Location

func Location() Action[string]

Location is an action that retrieves the document location.

func MatchedStyle

func MatchedStyle[S Selectable](sel S, opts ...QueryOption) Action[*css.GetMatchedStylesForNodeResult]

MatchedStyle is an element query action that retrieves the matched style information for the first element node matching the selector.

func MouseClickNode

func MouseClickNode(n *Node, opts ...MouseOption) Action[Void]

MouseClickNode is an action that dispatches a left mouse button click event at the center of a node.

Note: the action scrolls the window if the node is not within the viewport of the window.

func MouseClickXY

func MouseClickXY(x, y float64, opts ...MouseOption) Action[Void]

MouseClickXY is an action that sends a left mouse button click (that is, a mousePressed and a mouseReleased event) to the X, Y location.

func MouseEvent added in v0.4.0

func MouseEvent(typ input.DispatchMouseEventType, x, y float64, opts ...MouseOption) Action[Void]

MouseEvent is a mouse event action to dispatch the specified mouse event type at coordinates x, y.

func Navigate(urlstr string) Action[Void]

Navigate is an action that navigates the current frame and waits for the page to load.

This action does not collect HTTP response information. To get it, use NavigateResponse or RunResponse.

func NavigateBack() Action[Void]

NavigateBack is an action that navigates the current frame backwards in its history, and waits for the page to load.

func NavigateForward() Action[Void]

NavigateForward is an action that navigates the current frame forwards in its history, and waits for the page to load.

func NavigateResponse(urlstr string) Action[*network.Response]

NavigateResponse is like Navigate, and returns the HTTP response of the HTML document.

func NavigateToHistoryEntry(entryID int64) Action[Void]

NavigateToHistoryEntry is an action to navigate to the specified navigation entry, and wait for the page to load.

func NavigationEntries() Action[page.GetNavigationHistoryResult]

NavigationEntries is an action that retrieves the page's navigation history entries. The result holds the index of the current entry and the entries.

func Nodes

func Nodes[S Selectable](sel S, opts ...QueryOption) Action[[]*Node]

Nodes is an element query action that retrieves the document element nodes matching the selector.

func OuterHTML

func OuterHTML[S Selectable](sel S, opts ...QueryOption) Action[string]

OuterHTML is an element query action that retrieves the outer html of the first element node matching the selector.

func Poll added in v0.6.11

func Poll[T any](expression string, opts ...PollOption) Action[T]

Poll is a poll action that waits for a general JavaScript predicate. It builds the predicate from a JavaScript expression.

This is a copy of page.waitForFunction of puppeteer. It is named Poll on purpose, so that it does not mix with the Wait* query actions. The behavior is not guaranteed to be compatible. For example, in our implementation the poll task does not survive a navigation. In this case the action returns an error (see unit test TestPoll/NotSurviveNavigation).

Polling Options

The default polling mode is "raf". It runs pageFunction in a requestAnimationFrame callback all the time. This is the tightest polling mode, and it is suitable to observe styling changes. The WithPollingInterval option polls the predicate at a given interval. The WithPollingMutation option polls the predicate on every DOM mutation.

The WithPollingTimeout option sets the maximum time to wait until the predicate returns a truthy value. It defaults to 30 seconds. Pass 0 to disable the timeout.

The WithPollingInFrame option sets the frame in which to evaluate the predicate. Without it, the action evaluates the predicate in the root page of the current tab.

The WithPollingArgs option gives extra arguments to the predicate. Use this option only when the predicate is built from a function. See PollFunction.

The action returns the truthy value of the predicate, decoded into the type T. T is handled as in Evaluate. Use Void when the value does not matter.

func PollFunction added in v0.6.11

func PollFunction[T any](pageFunction string, opts ...PollOption) Action[T]

PollFunction is a poll action that waits for a general JavaScript predicate. It builds the predicate from a JavaScript function.

See Poll for how to build poll tasks.

func Query

func Query[S Selectable](sel S, opts ...QueryOption) Action[Void]

Query is an action that queries the browser for element nodes that match the criteria, and waits until they meet the node conditions. It returns no value. To get the nodes, see Nodes.

Query actions that target element nodes share one selector. Use the After option or QueryAfter to read data from the selected elements or to change them.

For example:

chromedp.Do(ctx, chromedp.SendKeys(chromedp.ID("thing"), "hello"))

This runs a SendKeys action on the first element that has the id "thing".

Element selection queries work with specific actions. They are the main way to automate steps in the browser. They have this form:

Action(selector[, parameter1, ...parameterN][, queryOptions...])

Where:

  • Action - the action to run
  • selector - the element query, a Selectable value. The action applies to every node that matches it.
  • parameter[1-N] - the parameters that the action needs (if any)
  • queryOptions - change how the query runs, or how it waits for nodes

An action that reads a value returns it. For example, Text returns the text as a string.

Selectors

The type of the selector chooses the lookup that the browser runs. A plain string, or any other string type that this package does not define, is a Search.

The Search type (the default) queries elements by plain text, CSS selector, or XPath query. It wraps DOM.performSearch.

The ID type queries a single element by its CSS ID. It wraps DOM.querySelector. ID is like document.querySelector('#' + ID) in the browser.

The CSS type queries a single element with a CSS selector. It wraps DOM.querySelector. CSS is like document.querySelector() in the browser.

The CSSAll type queries elements with a CSS selector. It wraps DOM.querySelectorAll. CSSAll is like document.querySelectorAll() in the browser.

The JSPath type queries a single element by its "JS Path" value. It wraps Runtime.evaluate. JSPath is like a JavaScript snippet that returns an element in the browser. Use it only with trusted element queries. chromedp passes the query directly to Runtime.evaluate and does not sanitize it. The type is useful for DOM elements that the other types cannot retrieve, such as ShadowDOM elements.

The NodeIDs type selects the elements with the given node IDs. It uses DOM.requestChildNodes to retrieve them.

A type outside the Selectable set, such as an int or a *Node, does not compile.

Query Options

The Node* options set node conditions. The query waits until the condition is true. Without a Node* option, the query uses the NodeReady condition.

The AtLeast option sets the minimum number of nodes that the query must return. The default is 1.

The After option sets a func that runs after the query returns one or more elements and the node condition is true.

The ByFunc option replaces the lookup of the selector with a custom func.

Node Options

The NodeReady option (the default) makes the query wait until the browser has returned all element nodes that match the selector.

The NodeVisible option makes the query wait until the browser has returned all element nodes that match the selector, and they are visible.

The NodeNotVisible option makes the query wait until the browser has returned all element nodes that match the selector, and they are not visible.

The NodeEnabled option makes the query wait until the browser has returned all element nodes that match the selector. The nodes must be enabled (that is, they have no 'disabled' attribute).

The NodeSelected option makes the query wait until the browser has returned all element nodes that match the selector. The nodes must be selected (that is, they have a 'selected' attribute).

The NodeNotPresent option makes the query wait until no element node matches the selector.

func QueryAfter

func QueryAfter[T any, S Selectable](sel S, f func(ctx context.Context, t *Target, nodes []*Node) (T, error), opts ...QueryOption) Action[T]

QueryAfter is an element query action that queries the browser for selector sel. It waits until the node conditions of the query are met, then runs f and returns its value.

func QueryNodeIDs added in v0.17.0

func QueryNodeIDs[S Selectable](sel S, opts ...QueryOption) Action[[]cdp.NodeID]

QueryNodeIDs is an element query action that retrieves the element node IDs matching the selector.

func Reload

func Reload() Action[Void]

Reload is an action that reloads the current page, and waits for the page to load.

func RemoveAttribute

func RemoveAttribute[S Selectable](sel S, name string, opts ...QueryOption) Action[Void]

RemoveAttribute is an element query action that removes the element attribute with name from the first element node matching the selector.

func Reset

func Reset[S Selectable](sel S, opts ...QueryOption) Action[Void]

Reset is an element query action that resets the parent form of the first element node matching the selector.

func ResetViewport added in v0.4.0

func ResetViewport() Action[Void]

ResetViewport is an action that resets the browser viewport to the values that the browser started with.

Note: it does not change the emulated User-Agent of the browser, if any.

func Screenshot

func Screenshot[S Selectable](sel S, opts ...QueryOption) Action[[]byte]

Screenshot is an element query action that takes a screenshot of the first element node that matches the selector.

It acts like the command "Capture node screenshot" in Chrome.

Behavior notes: the Protocol Monitor shows that the command also sends these protocol commands:

  • Emulation.clearDeviceMetricsOverride
  • Network.setUserAgentOverride with {"userAgent": ""}
  • Overlay.setShowViewportSizeOnResize with {"show": false}

chromedp does not send these protocol commands. If the result is not what you expect, send them yourself.

To capture the browser viewport, see CaptureScreenshot.

For an example that takes a screenshot of the entire page, see screenshot.

func ScreenshotNodes added in v0.9.4

func ScreenshotNodes(nodes []*Node, scale float64) Action[[]byte]

ScreenshotNodes is an action that takes a screenshot of the specified nodes. It calculates the extents from the top most left node and the bottom most right node.

func ScreenshotScale added in v0.9.3

func ScreenshotScale[S Selectable](sel S, scale float64, opts ...QueryOption) Action[[]byte]

ScreenshotScale is like Screenshot but takes a scale parameter, which is the page scale factor.

func ScrollIntoView

func ScrollIntoView[S Selectable](sel S, opts ...QueryOption) Action[Void]

ScrollIntoView is an element query action that scrolls the window to the first element node matching the selector.

func SendKeys

func SendKeys[S Selectable](sel S, v string, opts ...QueryOption) Action[Void]

SendKeys is an element query action that sends key events to the first element node that matches the selector. It synthesizes the key down, char, and key up events that the runes in v need.

See keys for a complete example of how to use SendKeys.

Note: when the element query matches an input[type="file"] node, SendKeys uses dom.SetFileInputFiles to set the upload path of the input node to v.

Example
package main

import (
	"context"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/httptest"
	"strings"

	"github.com/chromedp/chromedp"
)

func writeHTML(content string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		io.WriteString(w, strings.TrimSpace(content))
	})
}

func main() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	ts := httptest.NewServer(writeHTML(`
<body>
<form id="form"><input id="name" name="name"/><input id="color" name="color"/></form>
</body>
	`))
	defer ts.Close()

	if err := chromedp.Do(ctx,
		chromedp.Navigate(ts.URL),
		chromedp.SendKeys(chromedp.ID("name"), "Ada"),
		chromedp.SetValue(chromedp.ID("color"), "green"),
	); err != nil {
		log.Fatal(err)
	}
	name, err := chromedp.Run(ctx, chromedp.Value(chromedp.ID("name")))
	if err != nil {
		log.Fatal(err)
	}
	color, err := chromedp.Run(ctx, chromedp.Value(chromedp.ID("color")))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(name, color)

}
Output:
Ada green

func SetAttributeValue

func SetAttributeValue[S Selectable](sel S, name, value string, opts ...QueryOption) Action[Void]

SetAttributeValue is an element query action that sets the element attribute with name to value for the first element node matching the selector.

func SetAttributes

func SetAttributes[S Selectable](sel S, attributes map[string]string, opts ...QueryOption) Action[Void]

SetAttributes is an element query action that sets the element attributes for the first element node matching the selector.

func SetJavascriptAttribute

func SetJavascriptAttribute[S Selectable](sel S, name, value string, opts ...QueryOption) Action[Void]

SetJavascriptAttribute is an element query action that sets the JavaScript attribute for the first element node matching the selector.

func SetUploadFiles

func SetUploadFiles[S Selectable](sel S, files []string, opts ...QueryOption) Action[Void]

SetUploadFiles is an element query action that sets the files to upload for the first element node matching the selector. The node must be an input[type="file"] node.

func SetValue

func SetValue[S Selectable](sel S, value string, opts ...QueryOption) Action[Void]

SetValue is an element query action that sets the JavaScript value of the first element node matching the selector.

Use it to set the JavaScript value of a form, input, textarea, select, or other element with a '.value' field.

func Sleep

func Sleep(d time.Duration) Action[Void]

Sleep is an action that waits for the duration, or until the context ends.

func Steps added in v0.17.0

func Steps(steps ...Action[Void]) Action[Void]

Steps joins the actions into one action that runs them in order and stops at the first error. It replaces the type Tasks.

func Stop

func Stop() Action[Void]

Stop is an action that stops all navigation and pending resource retrieval.

func Submit

func Submit[S Selectable](sel S, opts ...QueryOption) Action[Void]

Submit is an element query action that submits the parent form of the first element node matching the selector.

func Text

func Text[S Selectable](sel S, opts ...QueryOption) Action[string]

Text is an element query action that retrieves the visible text of the first element node matching the selector.

func TextContent added in v0.4.1

func TextContent[S Selectable](sel S, opts ...QueryOption) Action[string]

TextContent is an element query action that retrieves the text content of the first element node matching the selector.

func Title

func Title() Action[string]

Title is an action that retrieves the document title.

Example
package main

import (
	"context"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/httptest"
	"strings"

	"github.com/chromedp/chromedp"
)

func writeHTML(content string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		io.WriteString(w, strings.TrimSpace(content))
	})
}

func main() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	ts := httptest.NewServer(writeHTML(`
<head>
	<title>fancy website title</title>
</head>
<body>
	<div id="content"></div>
</body>
	`))
	defer ts.Close()

	if err := chromedp.Do(ctx, chromedp.Navigate(ts.URL)); err != nil {
		log.Fatal(err)
	}
	title, err := chromedp.Run(ctx, chromedp.Title())
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(title)

}
Output:
fancy website title

func Value

func Value[S Selectable](sel S, opts ...QueryOption) Action[string]

Value is an element query action that retrieves the JavaScript value field of the first element node matching the selector.

Use it to read the JavaScript value of a form, input, textarea, select, or other element with a '.value' field.

func WaitEnabled

func WaitEnabled[S Selectable](sel S, opts ...QueryOption) Action[Void]

WaitEnabled is an element query action that waits until the element that matches the selector is enabled (that is, it has no attribute 'disabled').

func WaitEvent added in v0.17.0

func WaitEvent[E, T any](ev cdp.Event[E], match func(E) bool, trigger Action[T]) Action[E]

WaitEvent makes an action that waits for an event. It subscribes to the event, runs the trigger action, and then returns the first payload for which match returns true. A nil match accepts every payload. The trigger runs after the subscription, so the event cannot arrive too early.

For example, to wait for the load event that a click causes:

_, err := chromedp.Run(ctx, chromedp.WaitEvent(page.LoadEventFired, nil,
	chromedp.Click(chromedp.CSS("a"))))

When the context ends before a matching event arrives, WaitEvent returns the error of the context.

func WaitNotPresent

func WaitNotPresent[S Selectable](sel S, opts ...QueryOption) Action[Void]

WaitNotPresent is an element query action that waits until no element that matches the selector is present.

func WaitNotVisible

func WaitNotVisible[S Selectable](sel S, opts ...QueryOption) Action[Void]

WaitNotVisible is an element query action that waits until the element matching the selector is not visible.

func WaitReady

func WaitReady[S Selectable](sel S, opts ...QueryOption) Action[Void]

WaitReady is an element query action that waits until the element that matches the selector is ready (that is, "loaded").

func WaitSelected

func WaitSelected[S Selectable](sel S, opts ...QueryOption) Action[Void]

WaitSelected is an element query action that waits until the element that matches the selector is selected (that is, it has the attribute 'selected').

func WaitVisible

func WaitVisible[S Selectable](sel S, opts ...QueryOption) Action[Void]

WaitVisible is an element query action that waits until the element matching the selector is visible.

type Allocator added in v0.2.0

type Allocator interface {
	// Allocate creates a new browser. Canceling the provided context frees all
	// resources of the browser, such as temporary directories.
	Allocate(context.Context, ...BrowserOption) (*Browser, error)

	// Wait blocks until the allocator has freed all of its resources.
	// Canceling the allocator context does this too, so normally you do not
	// need to call Wait.
	Wait()
}

An Allocator creates and manages a number of browsers.

This interface hides how the browser process runs. For example, an Allocator can reuse browser processes, or connect to browsers that already run on remote machines.

type AttributeResult added in v0.17.0

type AttributeResult struct {
	// Value is the value of the attribute. It is empty when the attribute
	// does not exist.
	Value string

	// Exists is true when the element has the attribute.
	Exists bool
}

AttributeResult is the result of the AttributeValue action.

type Browser added in v0.2.0

type Browser struct {

	// LostConnection is closed when the connection to Chrome drops. The
	// connection is a pipe or a websocket.
	// Use it to make sure that the context of the Browser is canceled (and the
	// handler stopped) after the connection fails.
	LostConnection chan struct{}
	// contains filtered or unexported fields
}

Browser manages a browser through the Chrome DevTools Protocol. It handles the browser process runner, the connection to the browser, the targets, and the network, page, and DOM events. The connection is a pipe or a websocket.

func NewBrowser added in v0.2.0

func NewBrowser(ctx context.Context, urlstr string, opts ...BrowserOption) (*Browser, error)

NewBrowser creates a new browser. Typically you do not call it directly, because the Allocator interface does it.

It dials the websocket address urlstr. To use a connection that is already open, see NewBrowserTransport.

func NewBrowserTransport added in v0.17.0

func NewBrowserTransport(ctx context.Context, tr Transport, opts ...BrowserOption) (*Browser, error)

NewBrowserTransport creates a new browser that uses tr, a connection to a browser that is already open, such as a *PipeConn. The browser closes tr when it stops.

func (*Browser) Call added in v0.17.0

func (b *Browser) Call(ctx context.Context, method string, params, res any) error

Call sends the command to the browser, waits for the response, and decodes the result into res. It satisfies cdp.Session.

Call returns a browser error as a *cdproto.Error.

func (*Browser) Process added in v0.7.2

func (b *Browser) Process() *os.Process

Process returns the process object of the browser.

It is nil when the browser was allocated with RemoteAllocator. A monitoring system can use it to collect process metrics of the browser process (see prometheus.NewProcessCollector for an example).

Example:

if process := chromedp.FromContext(ctx).Browser.Process(); process != nil {
	fmt.Printf("Browser PID: %v", process.Pid)
}

func (*Browser) Subscribe added in v0.17.0

func (b *Browser) Subscribe(method string) (<-chan jsontext.Value, func())

Subscribe starts to buffer the browser events with the method, and returns the channel that the raw event parameters arrive on. It satisfies cdp.Session.

type BrowserOption added in v0.2.0

type BrowserOption = func(*Browser)

BrowserOption is a browser option.

func WithBrowserDebugf added in v0.2.0

func WithBrowserDebugf(f func(string, ...any)) BrowserOption

WithBrowserDebugf is a browser option that sets the func that receives the protocol messages.

func WithBrowserErrorf added in v0.2.0

func WithBrowserErrorf(f func(string, ...any)) BrowserOption

WithBrowserErrorf is a browser option that sets the func that receives error messages.

func WithBrowserLogf added in v0.2.0

func WithBrowserLogf(f func(string, ...any)) BrowserOption

WithBrowserLogf is a browser option that sets the func that receives general log messages.

func WithConsolef

func WithConsolef(f func(string, ...any)) BrowserOption

WithConsolef is a browser option that sets the func that receives chrome log events.

Note: it is not implemented yet.

func WithDialTimeout added in v0.3.0

func WithDialTimeout(d time.Duration) BrowserOption

WithDialTimeout is a browser option that sets the timeout for dialing the websocket address of the browser. The default is ten seconds. Use a zero duration for no timeout.

type CSS added in v0.17.0

type CSS string

CSS is a selector for the first element that matches a CSS selector. It uses DOM.querySelector.

type CSSAll added in v0.17.0

type CSSAll string

CSSAll is a selector for every element that matches a CSS selector. It uses DOM.querySelectorAll.

type CallOption added in v0.7.4

type CallOption = func(params *runtime.CallFunctionOnParams)

CallOption is a func that changes the runtime.CallFunctionOnParams of a call.

type Conn added in v0.2.0

type Conn struct {
	// contains filtered or unexported fields
}

Conn implements Transport with a gobwas/ws websocket connection.

func DialContext added in v0.2.0

func DialContext(ctx context.Context, urlstr string, opts ...DialOption) (*Conn, error)

DialContext dials the websocket URL with gobwas/ws.

func (*Conn) Close added in v0.2.0

func (c *Conn) Close() error

Close satisfies the io.Closer interface.

func (*Conn) Read added in v0.2.0

func (c *Conn) Read(_ context.Context, msg *cdproto.Message) error

Read reads the next message.

func (*Conn) Write added in v0.2.0

func (c *Conn) Write(_ context.Context, msg *cdproto.Message) error

Write writes a message.

type Context added in v0.2.0

type Context struct {
	// Allocator creates new browsers. A child context inherits it from the
	// parent context.
	Allocator Allocator

	// Browser is the browser of the context. A child context inherits it from
	// the parent context.
	Browser *Browser

	// Target is the target that actions run against. A child context does not
	// inherit it. Typically each context has its own Target, which points to a
	// separate browser tab (page).
	Target *Target

	// BrowserContextID is set by WithExistingBrowserContext.
	//
	// Otherwise, BrowserContextID is not empty in these cases:
	//
	// 1. The context was made with WithNewBrowserContext. Its first run creates
	// a new BrowserContext, and BrowserContextID holds the id of that
	// BrowserContext.
	//
	// 2. The context was not made with WithTargetID, and the parent context
	// has a BrowserContextID that is not empty. The context copies it from the
	// parent context.
	BrowserContextID cdp.BrowserContextID
	// contains filtered or unexported fields
}

Context is the data that NewContext stores in a context.Context. Run needs it.

func FromContext added in v0.2.0

func FromContext(ctx context.Context) *Context

FromContext returns the Context that a context.Context holds, or nil.

type ContextOption added in v0.2.0

type ContextOption = func(*Context)

ContextOption is a context option.

func WithBrowserOption added in v0.2.0

func WithBrowserOption(opts ...BrowserOption) ContextOption

WithBrowserOption passes browser options to the allocator when it allocates a new browser. As a result, you can use this option only when the context allocates a new browser.

func WithDebugf

func WithDebugf(f func(string, ...any)) ContextOption

WithDebugf is a shortcut for WithBrowserOption(WithBrowserDebugf(f)).

func WithErrorf

func WithErrorf(f func(string, ...any)) ContextOption

WithErrorf is a shortcut for WithBrowserOption(WithBrowserErrorf(f)).

func WithExistingBrowserContext added in v0.8.8

func WithExistingBrowserContext(id cdp.BrowserContextID) ContextOption

WithExistingBrowserContext makes a context create a new target in the given BrowserContext.

func WithKeepOpen added in v0.17.0

func WithKeepOpen() ContextOption

WithKeepOpen makes NewContext build the default allocator with KeepOpen. It works with headless mode too.

The option only applies when the parent context has no allocator. It has no effect on an allocator that the caller made, and it has no effect on a context that inherits a browser. For an allocator that you make, add KeepOpen to the options of NewExecAllocator instead.

Example

This example leaves the browser open when the program ends. The program prints the address, so that another program can attach with NewRemoteAllocator. The profile directory stays on disk, and the user must delete it.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/chromedp/chromedp"
)

func main() {
	ctx, cancel := chromedp.NewContext(context.Background(),
		chromedp.WithVisibleWindow(), chromedp.WithKeepOpen())
	defer cancel()

	if err := chromedp.Do(ctx, chromedp.Navigate("https://example.com")); err != nil {
		log.Fatal(err)
	}
	wsURL, profile := chromedp.KeptOpen(ctx)
	fmt.Println("attach to", wsURL)
	fmt.Println("profile directory", profile)
}

func WithLogf

func WithLogf(f func(string, ...any)) ContextOption

WithLogf is a shortcut for WithBrowserOption(WithBrowserLogf(f)).

func WithNewBrowserContext added in v0.8.8

func WithNewBrowserContext(options ...CreateBrowserContextOption) ContextOption

WithNewBrowserContext makes a context create a new BrowserContext and a new target in it. A child context creates its target in this BrowserContext too, unless another option applies. The context disposes the new BrowserContext when the context is done.

func WithTargetID added in v0.3.0

func WithTargetID(id target.ID) ContextOption

WithTargetID makes a context attach to an existing target, and not create a new one.

func WithVisibleWindow added in v0.17.0

func WithVisibleWindow() ContextOption

WithVisibleWindow makes NewContext build the default allocator with VisibleWindow and without Headless, so that the browser opens a visible window. The window stays open until the context ends. See also WithKeepOpen and WaitClosed.

The environment variable CHROMEDP_VISIBLEWINDOW has the same effect with no change in the code. Any value other than the empty string, "false" and "0" turns it on.

The option only applies when the parent context has no allocator, because then NewContext builds the allocator. It has no effect on an allocator that the caller made with NewExecAllocator or NewRemoteAllocator, and it has no effect on a context that inherits a browser. For an allocator that you make, add VisibleWindow to the options of NewExecAllocator instead.

On Linux, the first Run returns ErrNoDisplay when the environment has no display.

Example

This example opens a visible window and waits until the user closes it. The variable CHROMEDP_VISIBLEWINDOW=1 has the same effect as the option.

package main

import (
	"context"
	"log"

	"github.com/chromedp/chromedp"
)

func main() {
	ctx, cancel := chromedp.NewContext(context.Background(), chromedp.WithVisibleWindow())
	defer cancel()

	if err := chromedp.Do(ctx, chromedp.Navigate("https://example.com")); err != nil {
		log.Fatal(err)
	}
	// Block until the user closes the window.
	chromedp.WaitClosed(ctx)
}

type CreateBrowserContextOption added in v0.8.8

type CreateBrowserContextOption = func(*target.CreateBrowserContextParams)

CreateBrowserContextOption is an option for the creation of a BrowserContext.

type Device added in v0.4.0

type Device interface {
	// Device returns the device info.
	Device() device.Info
}

Device is the shared interface for known device types.

See device for a set of ready-made devices and modes.

type DialOption added in v0.2.0

type DialOption = func(*Conn)

DialOption is a dial option.

func WithConnDebugf added in v0.2.0

func WithConnDebugf(f func(string, ...any)) DialOption

WithConnDebugf is a dial option to set a protocol logger.

type EmulateViewportOption added in v0.4.0

EmulateViewportOption is the type for emulate viewport options.

func EmulateOrientation added in v0.4.0

func EmulateOrientation(orientation emulation.ScreenOrientationType, angle int64) EmulateViewportOption

EmulateOrientation is an emulate viewport option to set the device viewport screen orientation.

func EmulateScale added in v0.4.0

func EmulateScale(scale float64) EmulateViewportOption

EmulateScale is an emulate viewport option to set the device viewport scaling factor.

type Error

type Error string

Error is a chromedp error.

const (
	// ErrInvalidWebsocketMessage is the invalid websocket message.
	ErrInvalidWebsocketMessage Error = "invalid websocket message"

	// ErrInvalidDimensions is the invalid dimensions error.
	ErrInvalidDimensions Error = "invalid dimensions"

	// ErrNoResults is the no results error.
	ErrNoResults Error = "no results"

	// ErrHasResults is the has results error.
	ErrHasResults Error = "has results"

	// ErrNotVisible is the not visible error.
	ErrNotVisible Error = "not visible"

	// ErrVisible is the visible error.
	ErrVisible Error = "visible"

	// ErrDisabled is the disabled error.
	ErrDisabled Error = "disabled"

	// ErrNotSelected is the not selected error.
	ErrNotSelected Error = "not selected"

	// ErrInvalidBoxModel is the invalid box model error.
	ErrInvalidBoxModel Error = "invalid box model"

	// ErrChannelClosed is the channel closed error.
	ErrChannelClosed Error = "channel closed"

	// ErrInvalidTarget is the invalid target error.
	ErrInvalidTarget Error = "invalid target"

	// ErrNoDisplay is the error when a visible window is requested on Linux
	// and the environment has no display.
	ErrNoDisplay Error = "" /* 190-byte string literal not displayed */

	// ErrInvalidContext is the invalid context error.
	ErrInvalidContext Error = "invalid context"

	// ErrPollingTimeout is the error when the timeout ends before the pageFunction returns a truthy value.
	ErrPollingTimeout Error = "waiting for function failed: timeout"

	// ErrJSUndefined is the error that the type of RemoteObject is "undefined".
	ErrJSUndefined Error = "encountered an undefined value"

	// ErrJSNull is the error that the value of RemoteObject is null.
	ErrJSNull Error = "encountered a null value"
)

Error types.

func (Error) Error

func (err Error) Error() string

Error satisfies the error interface.

type EvaluateOption

type EvaluateOption = func(*runtime.EvaluateParams)

EvaluateOption is the type for JavaScript evaluation options.

func EvalObjectGroup

func EvalObjectGroup(objectGroup string) EvaluateOption

EvalObjectGroup is an evaluate option to set the object group.

type ExceptionError added in v0.17.0

type ExceptionError struct {
	*runtime.ExceptionDetails
}

ExceptionError is the error for a JavaScript exception. It wraps the protocol details of the exception.

func (*ExceptionError) Error added in v0.17.0

func (e *ExceptionError) Error() string

Error satisfies the error interface.

type ExecAllocator added in v0.2.0

type ExecAllocator struct {
	// contains filtered or unexported fields
}

ExecAllocator is an Allocator which starts new browser processes on the host machine.

Example
package main

import (
	"bytes"
	"context"
	"fmt"
	"log"
	"os"
	"path/filepath"

	"github.com/chromedp/chromedp"
)

func main() {
	dir, err := os.MkdirTemp("", "chromedp-example")
	if err != nil {
		log.Fatal(err)
	}
	defer os.RemoveAll(dir)

	opts := append(chromedp.DefaultExecAllocatorOptions[:],
		chromedp.DisableGPU,
		chromedp.UserDataDir(dir),
		// Chrome writes the DevToolsActivePort file only when it opens
		// a debugging port, so this example uses the websocket mode.
		chromedp.WebSocket,
	)

	allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
	defer cancel()

	// also set up a custom logger
	taskCtx, cancel := chromedp.NewContext(allocCtx, chromedp.WithLogf(log.Printf))
	defer cancel()

	// make sure that the browser process is started
	if err := chromedp.Do(taskCtx); err != nil {
		log.Fatal(err)
	}

	path := filepath.Join(dir, "DevToolsActivePort")
	bs, err := os.ReadFile(path)
	if err != nil {
		log.Fatal(err)
	}
	lines := bytes.Split(bs, []byte("\n"))
	fmt.Printf("DevToolsActivePort has %d lines\n", len(lines))

}
Output:
DevToolsActivePort has 2 lines

func (*ExecAllocator) Allocate added in v0.2.0

func (a *ExecAllocator) Allocate(ctx context.Context, opts ...BrowserOption) (*Browser, error)

Allocate satisfies the Allocator interface.

func (*ExecAllocator) Wait added in v0.2.0

func (a *ExecAllocator) Wait()

Wait satisfies the Allocator interface.

type ExecAllocatorOption added in v0.2.0

type ExecAllocatorOption = func(*ExecAllocator)

ExecAllocatorOption is an exec allocator option.

func CombinedOutput added in v0.4.0

func CombinedOutput(w io.Writer) ExecAllocatorOption

CombinedOutput sets the io.Writer that receives the stdout and stderr of the browser.

func Env added in v0.4.1

func Env(vars ...string) ExecAllocatorOption

Env sets environment variables, in the form NAME=value, for the new Chrome process. They add to the environment of the Go process, which os.Environ returns.

func ExecPath added in v0.2.0

func ExecPath(path string) ExecAllocatorOption

ExecPath returns an ExecAllocatorOption that uses the given path to run browser processes. The path can be an absolute path to a binary, or the name of a program that exec.LookPath finds.

func Flag added in v0.2.0

func Flag(name string, value any) ExecAllocatorOption

Flag is a generic command line option that passes a flag to Chrome. If the value is a string, Flag passes --name=value. If it is a boolean, Flag passes --name when the value is true.

func ModifyCmdFunc added in v0.7.3

func ModifyCmdFunc(f func(cmd *exec.Cmd)) ExecAllocatorOption

ModifyCmdFunc runs a func on the exec.Cmd of the browser. It replaces the default func, which sends SIGKILL to any open browsers when the Go program exits.

func ProxyServer added in v0.2.0

func ProxyServer(proxy string) ExecAllocatorOption

ProxyServer is the command line option to set the outbound proxy server.

func UserAgent added in v0.2.0

func UserAgent(userAgent string) ExecAllocatorOption

UserAgent is the command line option to set the default User-Agent header.

func UserDataDir added in v0.2.0

func UserDataDir(dir string) ExecAllocatorOption

UserDataDir is the command line option to set the user data directory. Use it to choose the profile directory of Chrome. Without it, ExecAllocator creates a default path in the /tmp directory.

func WSURLReadTimeout added in v0.8.4

func WSURLReadTimeout(t time.Duration) ExecAllocatorOption

WSURLReadTimeout sets how long ExecAllocator waits to read the WebSocket URL. The default is 20 seconds. It only applies to the websocket mode, see WebSocket.

func WindowSize added in v0.2.0

func WindowSize(width, height int) ExecAllocatorOption

WindowSize is the command line option to set the initial window size.

type Frame added in v0.17.0

type Frame struct {
	*cdp.Frame

	// State is the state of the frame.
	State FrameState
	// Root is the document root of the frame.
	Root *Node
	// Nodes holds the nodes of the frame by node id.
	Nodes map[cdp.NodeID]*Node

	sync.RWMutex
}

Frame is a frame of a page. It embeds the protocol frame and adds the node tree of the frame and the state that chromedp keeps up to date from the browser events.

Hold the lock of a Frame before you read a field that chromedp updates.

type FrameState added in v0.17.0

type FrameState uint16

FrameState is the state of a Frame.

const (
	FrameDOMContentEventFired FrameState = 1 << (15 - iota)
	FrameLoadEventFired
	FrameAttached
	FrameNavigated
	FrameLoading
	FrameScheduledNavigation
)

FrameState enum values.

func (FrameState) String added in v0.17.0

func (fs FrameState) String() string

String satisfies stringer interface.

type ID added in v0.17.0

type ID string

ID is a selector for the element with this id. A leading "#" is optional. It uses DOM.querySelector.

type JSPath added in v0.17.0

type JSPath string

JSPath is a selector for the element that a JavaScript expression gives. It uses Runtime.evaluate. Use it only with trusted values, because chromedp passes the expression to the browser without a check.

Example
package main

import (
	"context"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/httptest"
	"strings"

	"github.com/chromedp/cdproto/dom"
	"github.com/chromedp/chromedp"
)

func writeHTML(content string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		io.WriteString(w, strings.TrimSpace(content))
	})
}

func main() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	ts := httptest.NewServer(writeHTML(`
<body>
	<div id="content">cool content</div>
</body>
	`))
	defer ts.Close()

	if err := chromedp.Do(ctx, chromedp.Navigate(ts.URL)); err != nil {
		log.Fatal(err)
	}
	ids, err := chromedp.Run(ctx, chromedp.QueryNodeIDs(chromedp.JSPath(`document`)))
	if err != nil {
		log.Fatal(err)
	}
	res, err := chromedp.Call(ctx, dom.GetOuterHTML, dom.GetOuterHTMLParams{NodeID: ids[0]})
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("Outer HTML:")
	fmt.Println(res.OuterHTML)

}
Output:
Outer HTML:
<html><head></head><body>
	<div id="content">cool content</div>
</body></html>

type KeyOption

type KeyOption = func(*input.DispatchKeyEventParams)

KeyOption is a key action option.

func KeyModifiers

func KeyModifiers(modifiers ...Modifier) KeyOption

KeyModifiers is a key action option to add modifiers to the key press.

type Modifier added in v0.17.0

type Modifier = kb.Modifier

Modifier is a bit field of pressed modifier keys.

type MouseOption

type MouseOption = func(*input.DispatchMouseEventParams)

MouseOption is a mouse action option.

func Button

func Button(btn string) MouseOption

Button is a mouse action option to set the button to click from a string.

func ButtonModifiers

func ButtonModifiers(modifiers ...Modifier) MouseOption

ButtonModifiers is a mouse action option to add input modifiers for a button click.

func ButtonType

func ButtonType(button input.MouseButton) MouseOption

ButtonType is a mouse action option to set the button to click.

func ClickCount

func ClickCount(n int) MouseOption

ClickCount is a mouse action option to set the click count.

type Node added in v0.17.0

type Node struct {
	*cdp.Node

	// Parent is the parent node.
	Parent *Node
	// Children shadows the Children field of the protocol node.
	Children []*Node
	// ContentDocument shadows the ContentDocument field of the protocol node.
	ContentDocument *Node
	// ShadowRoots shadows the ShadowRoots field of the protocol node.
	ShadowRoots []*Node
	// TemplateContent shadows the TemplateContent field of the protocol node.
	TemplateContent *Node
	// PseudoElements shadows the PseudoElements field of the protocol node.
	PseudoElements []*Node

	// Invalidated is closed when the node is no longer valid.
	Invalidated chan struct{}
	// State is the state of the node.
	State NodeState

	sync.RWMutex
}

Node is a DOM node in the node tree of a frame. It embeds the protocol node and adds the tree links and the state that chromedp keeps up to date from the browser events.

Hold the lock of a Node before you read a field of the tree.

func (*Node) Attribute added in v0.17.0

func (n *Node) Attribute(name string) (string, bool)

Attribute returns the named attribute for the node and if it exists.

func (*Node) AttributeValue added in v0.17.0

func (n *Node) AttributeValue(name string) string

AttributeValue returns the named attribute for the node.

func (*Node) Dump added in v0.17.0

func (n *Node) Dump(prefix, indent string, nodeIDs bool) string

Dump builds a printable string representation of the node and its children.

func (*Node) FullXPath added in v0.17.0

func (n *Node) FullXPath() string

FullXPath returns the full XPath for the node. It stops only at the top most document root.

func (*Node) FullXPathByID added in v0.17.0

func (n *Node) FullXPathByID() string

FullXPathByID returns the full XPath for the node. It stops at the top most document root or at the closest parent node with an id attribute.

func (*Node) PartialXPath added in v0.17.0

func (n *Node) PartialXPath() string

PartialXPath returns the partial XPath for the node. It stops at the nearest parent document node.

func (*Node) PartialXPathByID added in v0.17.0

func (n *Node) PartialXPathByID() string

PartialXPathByID returns the partial XPath for the node. It stops at the first parent with an id attribute or at the nearest parent document node.

func (*Node) WriteTo added in v0.17.0

func (n *Node) WriteTo(w io.Writer, prefix, indent string, nodeIDs bool) (int, error)

WriteTo writes a readable representation of the node and all its children to w.

type NodeIDs

type NodeIDs []cdp.NodeID

NodeIDs is a selector for the elements with these node IDs.

type NodeState added in v0.17.0

type NodeState uint8

NodeState is the state of a DOM node.

const (
	NodeStateReady NodeState = 1 << (7 - iota)
	NodeStateVisible
	NodeStateHighlighted
)

NodeState enum values.

func (NodeState) String added in v0.17.0

func (ns NodeState) String() string

String satisfies stringer interface.

type NodeType added in v0.17.0

type NodeType int64

NodeType is the type of a DOM node. It is the value of the NodeType field of the protocol node.

func (NodeType) String added in v0.17.0

func (t NodeType) String() string

String returns the name of the node type.

type OldAction added in v0.17.0

type OldAction interface {
	// Do runs the action. The context holds the chromedp context.
	Do(context.Context) error
}

OldAction is the interface of an action of the previous version of chromedp. The previous version named it Action.

type PipeConn added in v0.17.0

type PipeConn struct {
	// contains filtered or unexported fields
}

PipeConn implements Transport with the two pipes of a browser that was started with the --remote-debugging-pipe flag.

The browser reads the commands from its file descriptor 3 and writes the responses and the events to its file descriptor 4. Each JSON message ends with one zero byte, in both directions.

func NewPipeConn added in v0.17.0

func NewPipeConn(r io.ReadCloser, w io.WriteCloser, opts ...PipeOption) *PipeConn

NewPipeConn returns a Transport that reads the messages of the browser from r and writes the messages for the browser to w. Close closes both r and w.

func (*PipeConn) Close added in v0.17.0

func (c *PipeConn) Close() error

Close satisfies the io.Closer interface. It closes both ends of the pipe, which makes the browser exit.

func (*PipeConn) Read added in v0.17.0

func (c *PipeConn) Read(_ context.Context, msg *cdproto.Message) error

Read reads the next message. It returns io.EOF when the browser closes its end of the pipe.

func (*PipeConn) Write added in v0.17.0

func (c *PipeConn) Write(_ context.Context, msg *cdproto.Message) error

Write writes a message. It is safe to call from more than one goroutine.

type PipeOption added in v0.17.0

type PipeOption = func(*PipeConn)

PipeOption is an option of NewPipeConn.

func WithPipeDebugf added in v0.17.0

func WithPipeDebugf(f func(string, ...any)) PipeOption

WithPipeDebugf is a pipe option to set a protocol logger.

type PollOption added in v0.6.11

type PollOption = func(task *pollTask)

PollOption is a poll task option.

func WithPollingArgs added in v0.6.11

func WithPollingArgs(args ...any) PollOption

WithPollingArgs provides extra arguments to pass to the predicate.

func WithPollingInFrame added in v0.6.11

func WithPollingInFrame(frame *Node) PollOption

WithPollingInFrame sets the frame in which to evaluate the predicate. Without it, the action evaluates the predicate in the root page of the current tab.

func WithPollingInterval added in v0.6.11

func WithPollingInterval(interval time.Duration) PollOption

WithPollingInterval polls the predicate at the given interval.

func WithPollingMutation added in v0.6.11

func WithPollingMutation() PollOption

WithPollingMutation polls the predicate on every DOM mutation.

func WithPollingTimeout added in v0.6.11

func WithPollingTimeout(timeout time.Duration) PollOption

WithPollingTimeout sets the maximum time to wait until the predicate returns a truthy value. It defaults to 30 seconds. Pass 0 to disable the timeout.

type PopulateOption added in v0.9.5

type PopulateOption = func(*time.Duration)

PopulateOption is an element populate action option.

func PopulateWait added in v0.9.5

func PopulateWait(wait time.Duration) PopulateOption

PopulateWait is a populate option that sets a wait interval after the request for child nodes.

type QueryOption

type QueryOption = func(*Selector)

QueryOption is an element query action option.

func After

func After(f func(ctx context.Context, t *Target, nodes []*Node) error) QueryOption

After is an element query option that sets a func to run when the browser has returned the matched nodes and the node condition is true.

func AtLeast

func AtLeast(n int) QueryOption

AtLeast is an element query option that sets the minimum number of elements that the query must return.

By default, a query needs 1.

func ByFunc

func ByFunc(f func(context.Context, *Target, *Node) ([]cdp.NodeID, error)) QueryOption

ByFunc is an element query action option that sets the func that selects elements. It replaces the lookup that the type of the selector chooses. The selector is then only a label in error messages, so pass "" or any string.

func FromNode added in v0.5.4

func FromNode(node *Node) QueryOption

FromNode is an element query action option that sets the node where the query runs. That is, the query looks only at the element sub-tree of the node. By default, or when you pass nil, the query uses the root element of the document.

Note: Search and JSPath selectors do not support FromNode now. The option is mainly useful for CSS selectors.

Example
package main

import (
	"context"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/httptest"
	"strings"

	"github.com/chromedp/chromedp"
)

func writeHTML(content string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		io.WriteString(w, strings.TrimSpace(content))
	})
}

func main() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	ts := httptest.NewServer(writeHTML(`
<body>
	<p class="content">outer content</p>
	<div id="section"><p class="content">inner content</p></div>
</body>
	`))
	defer ts.Close()

	if err := chromedp.Do(ctx, chromedp.Navigate(ts.URL)); err != nil {
		log.Fatal(err)
	}
	nodes, err := chromedp.Run(ctx, chromedp.Nodes(chromedp.CSS("#section")))
	if err != nil {
		log.Fatal(err)
	}
	sectionNode := nodes[0]

	// Queries run from the document root by default, so Text picks the
	// first node that it finds.
	queryRoot, err := chromedp.Run(ctx, chromedp.Text(chromedp.CSS(".content")))
	if err != nil {
		log.Fatal(err)
	}

	// We can choose a different node to run the query from. In this case,
	// we can narrow the search to #section.
	queryFromNode, err := chromedp.Run(ctx, chromedp.Text(chromedp.CSS(".content"), chromedp.FromNode(sectionNode)))
	if err != nil {
		log.Fatal(err)
	}

	// A CSS selector like "#section > .content" achieves the same here. But
	// FromNode accepts a node from an entirely separate step, so it allows
	// custom logic.
	queryNestedSelector, err := chromedp.Run(ctx, chromedp.Text(chromedp.CSS("#section > .content")))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Simple query from the document root:", queryRoot)
	fmt.Println("Simple query from the section node:", queryFromNode)
	fmt.Println("Nested query from the document root:", queryNestedSelector)

}
Output:
Simple query from the document root: outer content
Simple query from the section node: inner content
Nested query from the document root: inner content

func Populate added in v0.9.5

func Populate(depth int64, pierce bool, opts ...PopulateOption) QueryOption

Populate is an element query option that retrieves the queried nodes for later use. Use a depth of -1 to retrieve all child nodes. When pierce is true, it also pierces child containers (for example iframes).

NOTE: this can use a lot of resources. Use it only when necessary.

func RetryInterval added in v0.8.6

func RetryInterval(interval time.Duration) QueryOption

RetryInterval is an element query action option that sets how often the query retries when it fails to select the target elements.

The default is 5ms.

func WaitFunc

func WaitFunc(wait func(context.Context, *Target, *Frame, runtime.ExecutionContextID, ...cdp.NodeID) ([]*Node, error)) QueryOption

WaitFunc is an element query option to set a custom node condition wait.

type RemoteAllocator added in v0.2.0

type RemoteAllocator struct {
	// contains filtered or unexported fields
}

RemoteAllocator is an Allocator which connects to an already running Chrome process through a websocket URL.

func (*RemoteAllocator) Allocate added in v0.2.0

func (a *RemoteAllocator) Allocate(ctx context.Context, opts ...BrowserOption) (*Browser, error)

Allocate satisfies the Allocator interface.

func (*RemoteAllocator) Wait added in v0.2.0

func (a *RemoteAllocator) Wait()

Wait satisfies the Allocator interface.

type RemoteAllocatorOption added in v0.8.7

type RemoteAllocatorOption = func(*RemoteAllocator)

RemoteAllocatorOption is a remote allocator option.

type Search string

Search is a selector that the browser resolves with DOM.performSearch. It matches nodes by plain text, CSS selector or XPath query. It is the lookup of a plain string.

type Selectable added in v0.17.0

type Selectable interface {
	~string | ~[]cdp.NodeID
}

Selectable is what an element query accepts as the selector. The type of the selector chooses the lookup. A plain string is a Search. A named string type that this package does not define also counts as a Search.

Example
package main

import (
	"context"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/httptest"
	"strings"

	"github.com/chromedp/chromedp"
)

func writeHTML(content string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		io.WriteString(w, strings.TrimSpace(content))
	})
}

func main() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	ts := httptest.NewServer(writeHTML(`
<body>
	<p id="a" class="item">first</p>
	<p id="b" class="item">second</p>
</body>
	`))
	defer ts.Close()

	if err := chromedp.Do(ctx, chromedp.Navigate(ts.URL)); err != nil {
		log.Fatal(err)
	}

	// The type of the selector chooses the lookup. A plain string is a
	// Search, which takes a CSS selector, an XPath query or text.
	plain, err := chromedp.Run(ctx, chromedp.Text("#a"))
	if err != nil {
		log.Fatal(err)
	}
	// CSS selects the first match of a CSS selector.
	css, err := chromedp.Run(ctx, chromedp.Text(chromedp.CSS(".item")))
	if err != nil {
		log.Fatal(err)
	}
	// CSSAll selects every match of a CSS selector.
	all, err := chromedp.Run(ctx, chromedp.Nodes(chromedp.CSSAll(".item")))
	if err != nil {
		log.Fatal(err)
	}
	// ID selects the element with an id.
	id, err := chromedp.Run(ctx, chromedp.Text(chromedp.ID("b")))
	if err != nil {
		log.Fatal(err)
	}
	// NodeIDs selects the nodes with these ids.
	ids, err := chromedp.Run(ctx, chromedp.QueryNodeIDs(chromedp.CSSAll(".item")))
	if err != nil {
		log.Fatal(err)
	}
	byNodeIDs, err := chromedp.Run(ctx, chromedp.Text(chromedp.NodeIDs(ids[1:])))
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(plain, css, len(all), id, byNodeIDs)

	// A type outside of the Selectable set does not compile. Both calls
	// below are errors at build time, not at run time:
	//
	//	chromedp.Click(42)
	//	chromedp.Click(node)

}
Output:
first first 2 second second

type Selector

type Selector struct {
	// contains filtered or unexported fields
}

Selector holds the data of an element selection query.

See Query for how to build an element selector and its options.

type Target added in v0.2.0

type Target struct {
	SessionID target.SessionID
	TargetID  target.ID
	// contains filtered or unexported fields
}

Target manages a Chrome DevTools Protocol target.

func (*Target) Call added in v0.17.0

func (t *Target) Call(ctx context.Context, method string, params, res any) error

Call sends the command to the target, waits for the response, and decodes the result into res. It satisfies cdp.Session.

Call returns a browser error as a *cdproto.Error.

func (*Target) Subscribe added in v0.17.0

func (t *Target) Subscribe(method string) (<-chan jsontext.Value, func())

Subscribe starts to buffer the target events with the method, and returns the channel that the raw event parameters arrive on. It satisfies cdp.Session.

type Transport added in v0.2.0

type Transport interface {
	Read(context.Context, *cdproto.Message) error
	Write(context.Context, *cdproto.Message) error
	io.Closer
}

Transport is the common interface to send and receive the protocol messages of a browser. Conn and PipeConn implement it. Browser reads and writes its messages through it, and NewBrowserTransport accepts any Transport.

type Void added in v0.17.0

type Void = struct{}

Void is the result type of an action that returns no value.

Directories

Path Synopsis
Package device contains device emulation definitions for use with chromedp's Emulate action.
Package device contains device emulation definitions for use with chromedp's Emulate action.
Package kb provides keyboard mappings for Chrome DOM Keys for use with input events.
Package kb provides keyboard mappings for Chrome DOM Keys for use with input events.
remote module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL