diff --git a/docs/src/api/class-page.md b/docs/src/api/class-page.md index 917a35bf02..eb0b3849c6 100644 --- a/docs/src/api/class-page.md +++ b/docs/src/api/class-page.md @@ -1,9 +1,10 @@ + # class: Page * extends: [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter) -Page provides methods to interact with a single tab in a [Browser], or an [extension background -page](https://developer.chrome.com/extensions/background_pages) in Chromium. One [Browser] instance might have multiple -[Page] instances. +Page provides methods to interact with a single tab in a [Browser], or an +[extension background page](https://developer.chrome.com/extensions/background_pages) in Chromium. One [Browser] +instance might have multiple [Page] instances. This example creates a page, navigates it to a URL, and then saves a screenshot: @@ -20,6 +21,41 @@ const { webkit } = require('playwright'); // Or 'chromium' or 'firefox'. })(); ``` +```python async +import asyncio +from playwright.async_api import async_playwright + +async def run(playwright): + webkit = playwright.webkit + browser = await webkit.launch() + context = await browser.new_context() + page = await context.new_page() + await page.goto("https://example.com") + await page.screenshot(path="screenshot.png") + await browser.close() + +async def main(): + async with async_playwright() as playwright: + await run(playwright) +asyncio.run(main()) +``` + +```python sync +from playwright.sync_api import sync_playwright + +def run(playwright): + webkit = playwright.webkit + browser = webkit.launch() + context = browser.new_context() + page = context.new_page() + page.goto("https://example.com") + page.screenshot(path="screenshot.png") + browser.close() + +with sync_playwright() as playwright: + run(playwright) +``` + The Page class emits various events (described below) which can be handled using any of Node's native [`EventEmitter`](https://nodejs.org/api/events.html#events_class_eventemitter) methods, such as `on`, `once` or `removeListener`. @@ -30,6 +66,10 @@ This example logs a message for a single page `load` event: page.once('load', () => console.log('Page loaded!')); ``` +```py +page.once("load", lambda: print("page loaded!")) +``` + To unsubscribe from events use the `removeListener` method: ```js @@ -41,6 +81,14 @@ page.on('request', logRequest); page.removeListener('request', logRequest); ``` +```py +def log_request(intercepted_request): + print("a request was made:", intercepted_request.url) +page.on("request", log_request) +# sometime later... +page.remove_listener("request", log_request) +``` + ## event: Page.close Emitted when the page closes. @@ -58,11 +106,29 @@ An example of handling `console` event: ```js page.on('console', msg => { for (let i = 0; i < msg.args().length; ++i) - console.log(`${i}: ${msg.args()[i]}`); + console.log(`${i}: ${await msg.args()[i].jsonValue()}`); }); page.evaluate(() => console.log('hello', 5, {foo: 'bar'})); ``` +```python async +async def print_args(msg): + for arg in msg.args: + print(await arg.json_value()) + +page.on("console", print_args) +await page.evaluate("console.log('hello', 5, {foo: 'bar'})") +``` + +```python sync +def print_args(msg): + for arg in msg.args: + print(arg.json_value()) + +page.on("console", print_args) +page.evaluate("console.log('hello', 5, {foo: 'bar'})") +``` + ## event: Page.crash Emitted when the page crashes. Browser pages might crash if they try to allocate too much memory. When the page crashes, @@ -81,17 +147,24 @@ try { } ``` -However, when manually listening to events, it might be useful to avoid stalling when the page crashes. In this case, -handling `crash` event helps: +```python async +try: + # crash might happen during a click. + await page.click("button") + # or while waiting for an event. + await page.wait_for_event("popup") +except Error as e: + # when the page crashes, exception message contains "crash". +``` -```js -await new Promise((resolve, reject) => { - page.on('requestfinished', async request => { - if (await someProcessing(request)) - resolve(request); - }); - page.on('crash', error => reject(error)); -}); +```python sync +try: + # crash might happen during a click. + page.click("button") + # or while waiting for an event. + page.wait_for_event("popup") +except Error as e: + # when the page crashes, exception message contains "crash". ``` ## event: Page.dialog @@ -113,9 +186,8 @@ Emitted when attachment download started. User can access basic file operations :::note Browser context **must** be created with the [`option: acceptDownloads`] set to `true` when user needs access to the -downloaded content. If [`option: acceptDownloads`] is not set, download events -are emitted, but the actual download is not performed and user has no access to -the downloaded files. +downloaded content. If [`option: acceptDownloads`] is not set, download events are emitted, but the actual download is +not performed and user has no access to the downloaded files. ::: ## event: Page.filechooser @@ -130,6 +202,10 @@ page.on('filechooser', async (fileChooser) => { }); ``` +```py +page.on("filechooser", lambda file_chooser: file_chooser.set_files("/tmp/myfile.pdf")) +``` + ## event: Page.frameattached - type: <[Frame]> @@ -157,8 +233,8 @@ Emitted when an uncaught exception happens within the page. ## event: Page.popup - type: <[Page]> -Emitted when the page opens a new tab or window. This event is emitted in addition to the [`event: -BrowserContext.page`], but only for popups relevant to this page. +Emitted when the page opens a new tab or window. This event is emitted in addition to the +[`event: BrowserContext.page`], but only for popups relevant to this page. The earliest moment that page is available is when it has navigated to the initial url. For example, when opening a popup with `window.open('http://example.com')`, this event will fire when the network request to "http://example.com" is @@ -172,9 +248,23 @@ const [popup] = await Promise.all([ console.log(await popup.evaluate('location.href')); ``` +```python async +async with page.expect_event("popup") as page_info: + page.evaluate("window.open('https://example.com')") +popup = await page_info.value +print(await popup.evaluate("location.href")) +``` + +```python sync +with page.expect_event("popup") as page_info: + page.evaluate("window.open('https://example.com')") +popup = page_info.value +print(popup.evaluate("location.href")) +``` + :::note -Use [`method: Page.waitForLoadState`] to wait until the page gets to a particular state (you should not -need it in most cases). +Use [`method: Page.waitForLoadState`] to wait until the page gets to a particular state (you should not need it in most +cases). ::: ## event: Page.request @@ -189,8 +279,8 @@ Emitted when a page issues a request. The [request] object is read-only. In orde Emitted when a request fails, for example by timing out. :::note -HTTP Error responses, such as 404 or 503, are still successful responses from HTTP standpoint, so request -will complete with [`event: Page.requestfinished`] event and not with [`event: Page.requestfailed`]. +HTTP Error responses, such as 404 or 503, are still successful responses from HTTP standpoint, so request will complete +with [`event: Page.requestfinished`] event and not with [`event: Page.requestfailed`]. ::: ## event: Page.requestfinished @@ -246,11 +336,11 @@ Shortcut for main frame's [`method: Frame.$$`]. - returns: <[Serializable]> The method finds an element matching the specified selector within the page and passes it as a first argument to -[`param: pageFunction`]. If no elements match the selector, the method throws an error. Returns the value of [`param: -pageFunction`]. +[`param: pageFunction`]. If no elements match the selector, the method throws an error. Returns the value of +[`param: pageFunction`]. -If [`param: pageFunction`] returns a [Promise], then [`method: Page.$eval`] would wait for the promise to resolve and return its -value. +If [`param: pageFunction`] returns a [Promise], then [`method: Page.$eval`] would wait for the promise to resolve and +return its value. Examples: @@ -260,6 +350,18 @@ const preloadHref = await page.$eval('link[rel=preload]', el => el.href); const html = await page.$eval('.main-container', (e, suffix) => e.outerHTML + suffix, 'hello'); ``` +```python async +search_value = await page.eval_on_selector("#search", "el => el.value") +preload_href = await page.eval_on_selector("link[rel=preload]", "el => el.href") +html = await page.eval_on_selector(".main-container", "(e, suffix) => e.outer_html + suffix", "hello") +``` + +```python sync +search_value = page.eval_on_selector("#search", "el => el.value") +preload_href = page.eval_on_selector("link[rel=preload]", "el => el.href") +html = page.eval_on_selector(".main-container", "(e, suffix) => e.outer_html + suffix", "hello") +``` + Shortcut for main frame's [`method: Frame.$eval`]. ### param: Page.$eval.selector = %%-query-selector-%% @@ -283,13 +385,21 @@ Optional argument to pass to [`param: pageFunction`] The method finds all elements matching the specified selector within the page and passes an array of matched elements as a first argument to [`param: pageFunction`]. Returns the result of [`param: pageFunction`] invocation. -If [`param: pageFunction`] returns a [Promise], then [`method: Page.$$eval`] would wait for the promise to resolve and return -its value. +If [`param: pageFunction`] returns a [Promise], then [`method: Page.$$eval`] would wait for the promise to resolve and +return its value. Examples: ```js -const divsCounts = await page.$$eval('div', (divs, min) => divs.length >= min, 10); +const divCounts = await page.$$eval('div', (divs, min) => divs.length >= min, 10); +``` + +```python async +div_counts = await page.eval_on_selector_all("div", "(divs, min) => divs.length >= min", 10) +``` + +```python sync +div_counts = page.eval_on_selector_all("div", "(divs, min) => divs.length >= min", 10) ``` ### param: Page.$$eval.selector = %%-query-selector-%% @@ -312,7 +422,8 @@ Optional argument to pass to [`param: pageFunction`] Adds a script which would be evaluated in one of the following scenarios: * Whenever the page is navigated. -* Whenever the child frame is attached or navigated. In this case, the script is evaluated in the context of the newly attached frame. +* Whenever the child frame is attached or navigated. In this case, the script is evaluated in the context of the newly + attached frame. The script is evaluated after the document was created but before any of its scripts were run. This is useful to amend the JavaScript environment, e.g. to seed `Math.random`. @@ -322,10 +433,21 @@ An example of overriding `Math.random` before the page loads: ```js // preload.js Math.random = () => 42; +``` +```js // In your playwright script, assuming the preload.js file is in same directory -const preloadFile = fs.readFileSync('./preload.js', 'utf8'); -await page.addInitScript(preloadFile); +await page.addInitScript({ path: './preload.js' }); +``` + +```python async +# in your playwright script, assuming the preload.js file is in same directory +await page.add_init_script(path="./preload.js") +``` + +```python sync +# in your playwright script, assuming the preload.js file is in same directory +page.add_init_script(path="./preload.js") ``` :::note @@ -336,7 +458,8 @@ The order of evaluation of multiple scripts installed via [`method: BrowserConte ### param: Page.addInitScript.script * langs: js - `script` <[function]|[string]|[Object]> - - `path` <[path]> Path to the JavaScript file. If `path` is a relative path, then it is resolved relative to the current working directory. Optional. + - `path` <[path]> Path to the JavaScript file. If `path` is a relative path, then it is resolved relative to the + current working directory. Optional. - `content` <[string]> Raw script content. Optional. Script to be evaluated in the page. @@ -363,7 +486,8 @@ URL of a script to be added. ### option: Page.addScriptTag.path - `path` <[path]> -Path to the JavaScript file to be injected into frame. If `path` is a relative path, then it is resolved relative to the current working directory. +Path to the JavaScript file to be injected into frame. If `path` is a relative path, then it is resolved relative to the +current working directory. ### option: Page.addScriptTag.content - `content` <[string]> @@ -373,7 +497,8 @@ Raw JavaScript content to be injected into frame. ### option: Page.addScriptTag.type - `type` <[string]> -Script type. Use 'module' in order to load a Javascript ES6 module. See [script](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script) for more details. +Script type. Use 'module' in order to load a Javascript ES6 module. See +[script](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script) for more details. ## async method: Page.addStyleTag - returns: <[ElementHandle]> @@ -391,7 +516,8 @@ URL of the `` tag. ### option: Page.addStyleTag.path - `path` <[path]> -Path to the CSS file to be injected into frame. If `path` is a relative path, then it is resolved relative to the current working directory. +Path to the CSS file to be injected into frame. If `path` is a relative path, then it is resolved relative to the +current working directory. ### option: Page.addStyleTag.content - `content` <[string]> @@ -405,9 +531,12 @@ Brings page to front (activates tab). ## async method: Page.check This method checks an element matching [`param: selector`] by performing the following steps: -1. Find an element match matching [`param: selector`]. If there is none, wait until a matching element is attached to the DOM. -1. Ensure that matched element is a checkbox or a radio input. If not, this method rejects. If the element is already checked, this method returns immediately. -1. Wait for [actionability](./actionability.md) checks on the matched element, unless [`option: force`] option is set. If the element is detached during the checks, the whole action is retried. +1. Find an element match matching [`param: selector`]. If there is none, wait until a matching element is attached to + the DOM. +1. Ensure that matched element is a checkbox or a radio input. If not, this method rejects. If the element is already + checked, this method returns immediately. +1. Wait for [actionability](./actionability.md) checks on the matched element, unless [`option: force`] option is + set. If the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use [`property: Page.mouse`] to click in the center of the element. 1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set. @@ -429,8 +558,10 @@ Shortcut for main frame's [`method: Frame.check`]. ## async method: Page.click This method clicks an element matching [`param: selector`] by performing the following steps: -1. Find an element match matching [`param: selector`]. If there is none, wait until a matching element is attached to the DOM. -1. Wait for [actionability](./actionability.md) checks on the matched element, unless [`option: force`] option is set. If the element is detached during the checks, the whole action is retried. +1. Find an element match matching [`param: selector`]. If there is none, wait until a matching element is attached to + the DOM. +1. Wait for [actionability](./actionability.md) checks on the matched element, unless [`option: force`] option is + set. If the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use [`property: Page.mouse`] to click in the center of the element, or the specified [`option: position`]. 1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set. @@ -461,20 +592,20 @@ Shortcut for main frame's [`method: Frame.click`]. ## async method: Page.close If [`option: runBeforeUnload`] is `false`, does not run any unload handlers and waits for the page to be closed. If -[`option: runBeforeUnload`] is `true` the method will run unload handlers, but will **not** wait for the page to -close. +[`option: runBeforeUnload`] is `true` the method will run unload handlers, but will **not** wait for the page to close. By default, `page.close()` **does not** run `beforeunload` handlers. :::note -if [`option: runBeforeUnload`] is passed as true, a `beforeunload` dialog might be summoned and should be handled manually via [`event: Page.dialog`] event. +if [`option: runBeforeUnload`] is passed as true, a `beforeunload` dialog might be summoned and should be handled +manually via [`event: Page.dialog`] event. ::: ### option: Page.close.runBeforeUnload - `runBeforeUnload` <[boolean]> -Defaults to `false`. Whether to run the [before -unload](https://developer.mozilla.org/en-US/docs/Web/Events/beforeunload) page handlers. +Defaults to `false`. Whether to run the +[before unload](https://developer.mozilla.org/en-US/docs/Web/Events/beforeunload) page handlers. ## async method: Page.content - returns: <[string]> @@ -496,11 +627,14 @@ Browser-specific Coverage implementation, only available for Chromium atm. See ## async method: Page.dblclick This method double clicks an element matching [`param: selector`] by performing the following steps: -1. Find an element match matching [`param: selector`]. If there is none, wait until a matching element is attached to the DOM. -1. Wait for [actionability](./actionability.md) checks on the matched element, unless [`option: force`] option is set. If the element is detached during the checks, the whole action is retried. +1. Find an element match matching [`param: selector`]. If there is none, wait until a matching element is attached to + the DOM. +1. Wait for [actionability](./actionability.md) checks on the matched element, unless [`option: force`] option is + set. If the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use [`property: Page.mouse`] to double click in the center of the element, or the specified [`option: position`]. -1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set. Note that if the first click of the `dblclick()` triggers a navigation event, this method will reject. +1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set. Note that + if the first click of the `dblclick()` triggers a navigation event, this method will reject. When all steps combined have not finished during the specified [`option: timeout`], this method rejects with a [TimeoutError]. Passing zero timeout disables this. @@ -537,8 +671,17 @@ is dispatched. This is equivalend to calling await page.dispatchEvent('button#submit', 'click'); ``` -Under the hood, it creates an instance of an event based on the given [`param: type`], initializes it with [`param: -eventInit`] properties and dispatches it on the element. Events are `composed`, `cancelable` and bubble by default. +```python async +await page.dispatch_event("button#submit", "click") +``` + +```python sync +page.dispatch_event("button#submit", "click") +``` + +Under the hood, it creates an instance of an event based on the given [`param: type`], initializes it with +[`param: eventInit`] properties and dispatches it on the element. Events are `composed`, `cancelable` and bubble by +default. Since [`param: eventInit`] is event-specific, please refer to the events documentation for the lists of initial properties: @@ -558,6 +701,18 @@ const dataTransfer = await page.evaluateHandle(() => new DataTransfer()); await page.dispatchEvent('#source', 'dragstart', { dataTransfer }); ``` +```python async +# note you can only create data_transfer in chromium and firefox +data_transfer = await page.evaluate_handle("new DataTransfer()") +await page.dispatch_event("#source", "dragstart", { "dataTransfer": data_transfer }) +``` + +```python sync +# note you can only create data_transfer in chromium and firefox +data_transfer = page.evaluate_handle("new DataTransfer()") +page.dispatch_event("#source", "dragstart", { "dataTransfer": data_transfer }) +``` + ### param: Page.dispatchEvent.selector = %%-input-selector-%% ### param: Page.dispatchEvent.type @@ -593,6 +748,44 @@ await page.evaluate(() => matchMedia('print').matches); // → false ``` +```python async +await page.evaluate("matchMedia('screen').matches") +# → True +await page.evaluate("matchMedia('print').matches") +# → False + +await page.emulate_media(media="print") +await page.evaluate("matchMedia('screen').matches") +# → False +await page.evaluate("matchMedia('print').matches") +# → True + +await page.emulate_media() +await page.evaluate("matchMedia('screen').matches") +# → True +await page.evaluate("matchMedia('print').matches") +# → False +``` + +```python sync +page.evaluate("matchMedia('screen').matches") +# → True +page.evaluate("matchMedia('print').matches") +# → False + +page.emulate_media(media="print") +page.evaluate("matchMedia('screen').matches") +# → False +page.evaluate("matchMedia('print').matches") +# → True + +page.emulate_media() +page.evaluate("matchMedia('screen').matches") +# → True +page.evaluate("matchMedia('print').matches") +# → False +``` + ```js await page.emulateMedia({ colorScheme: 'dark' }); await page.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches); @@ -603,11 +796,34 @@ await page.evaluate(() => matchMedia('(prefers-color-scheme: no-preference)').ma // → false ``` +```python async +await page.emulate_media(color_scheme="dark") +await page.evaluate("matchMedia('(prefers-color-scheme: dark)').matches") +# → True +await page.evaluate("matchMedia('(prefers-color-scheme: light)').matches") +# → False +await page.evaluate("matchMedia('(prefers-color-scheme: no-preference)').matches") +# → False +``` + +```python sync +page.emulate_media(color_scheme="dark") +page.evaluate("matchMedia('(prefers-color-scheme: dark)').matches") +# → True +page.evaluate("matchMedia('(prefers-color-scheme: light)').matches") +# → False +page.evaluate("matchMedia('(prefers-color-scheme: no-preference)').matches") +``` + ### param: Page.emulateMedia.params * langs: js - `params` <[Object]> - - `media` <[null]|"screen"|"print"> Changes the CSS media type of the page. The only allowed values are `'screen'`, `'print'` and `null`. Passing `null` disables CSS media emulation. Omitting `media` or passing `undefined` does not change the emulated value. Optional. - - `colorScheme` <[null]|"light"|"dark"|"no-preference"> Emulates `'prefers-colors-scheme'` media feature, supported values are `'light'`, `'dark'`, `'no-preference'`. Passing `null` disables color scheme emulation. Omitting `colorScheme` or passing `undefined` does not change the emulated value. Optional. + - `media` <[null]|"screen"|"print"> Changes the CSS media type of the page. The only allowed values are + `'screen'`, `'print'` and `null`. Passing `null` disables CSS media emulation. Omitting `media` or passing + `undefined` does not change the emulated value. Optional. + - `colorScheme` <[null]|"light"|"dark"|"no-preference"> Emulates `'prefers-colors-scheme'` media feature, + supported values are `'light'`, `'dark'`, `'no-preference'`. Passing `null` disables color scheme emulation. + Omitting `colorScheme` or passing `undefined` does not change the emulated value. Optional. ## async method: Page.evaluate - returns: <[Serializable]> @@ -630,6 +846,16 @@ const result = await page.evaluate(([x, y]) => { console.log(result); // prints "56" ``` +```python async +result = await page.evaluate("([x, y]) => Promise.resolve(x * y)", [7, 8]) +print(result) # prints "56" +``` + +```python sync +result = page.evaluate("([x, y]) => Promise.resolve(x * y)", [7, 8]) +print(result) # prints "56" +``` + A string can also be passed in instead of a function: ```js @@ -638,6 +864,18 @@ const x = 10; console.log(await page.evaluate(`1 + ${x}`)); // prints "11" ``` +```python async +print(await page.evaluate("1 + 2")) # prints "3" +x = 10 +print(await page.evaluate(f"1 + {x}")) # prints "11" +``` + +```python sync +print(page.evaluate("1 + 2")) # prints "3" +x = 10 +print(page.evaluate(f"1 + {x}")) # prints "11" +``` + [ElementHandle] instances can be passed as an argument to the `page.evaluate`: ```js @@ -646,6 +884,18 @@ const html = await page.evaluate(([body, suffix]) => body.innerHTML + suffix, [b await bodyHandle.dispose(); ``` +```python async +body_handle = await page.query_selector("body") +html = await page.evaluate("([body, suffix]) => body.innerHTML + suffix", [body_handle, "hello"]) +await body_handle.dispose() +``` + +```python sync +body_handle = page.query_selector("body") +html = page.evaluate("([body, suffix]) => body.innerHTML + suffix", [body_handle, "hello"]) +body_handle.dispose() +``` + Shortcut for main frame's [`method: Frame.evaluate`]. ### param: Page.evaluate.pageFunction @@ -676,6 +926,14 @@ A string can also be passed in instead of a function: const aHandle = await page.evaluateHandle('document'); // Handle for the 'document' ``` +```python async +a_handle = await page.evaluate_handle("document") # handle for the "document" +``` + +```python sync +a_handle = page.evaluate_handle("document") # handle for the "document" +``` + [JSHandle] instances can be passed as an argument to the `page.evaluateHandle`: ```js @@ -685,6 +943,20 @@ console.log(await resultHandle.jsonValue()); await resultHandle.dispose(); ``` +```python async +a_handle = await page.evaluate_handle("document.body") +result_handle = await page.evaluate_handle("body => body.innerHTML", a_handle) +print(await result_handle.json_value()) +await result_handle.dispose() +``` + +```python sync +a_handle = page.evaluate_handle("document.body") +result_handle = page.evaluate_handle("body => body.innerHTML", a_handle) +print(result_handle.json_value()) +result_handle.dispose() +``` + ### param: Page.evaluateHandle.pageFunction * langs: js - `pageFunction` <[function]|[string]> @@ -699,11 +971,11 @@ Optional argument to pass to [`param: pageFunction`] ## async method: Page.exposeBinding The method adds a function called [`param: name`] on the `window` object of every frame in this page. When called, the -function executes [`param: callback`] and returns a [Promise] which resolves to the return value of [`param: -callback`]. If the [`param: callback`] returns a [Promise], it will be awaited. +function executes [`param: callback`] and returns a [Promise] which resolves to the return value of [`param: callback`]. +If the [`param: callback`] returns a [Promise], it will be awaited. -The first argument of the [`param: callback`] function contains information about the caller: `{ -browserContext: BrowserContext, page: Page, frame: Frame }`. +The first argument of the [`param: callback`] function contains information about the caller: `{ browserContext: +BrowserContext, page: Page, frame: Frame }`. See [`method: BrowserContext.exposeBinding`] for the context-wide version. @@ -734,6 +1006,57 @@ const { webkit } = require('playwright'); // Or 'chromium' or 'firefox'. })(); ``` +```python async +import asyncio +from playwright.async_api import async_playwright + +async def run(playwright): + webkit = playwright.webkit + browser = await webkit.launch(headless=false) + context = await browser.new_context() + page = await context.new_page() + await page.expose_binding("pageURL", lambda source: source["page"].url) + await page.set_content(""" + + +
+ """) + await page.click("button") + +async def main(): + async with async_playwright() as playwright: + await run(playwright) +asyncio.run(main()) +``` + +```python sync +from playwright.sync_api import sync_playwright + +def run(playwright): + webkit = playwright.webkit + browser = webkit.launch(headless=false) + context = browser.new_context() + page = context.new_page() + page.expose_binding("pageURL", lambda source: source["page"].url) + page.set_content(""" + + + + """) + page.click("button") + +with sync_playwright() as playwright: + run(playwright) +``` + An example of passing an element handle: ```js @@ -749,6 +1072,34 @@ await page.setContent(` `); ``` +```python async +async def print(source, element): + print(await element.text_content()) + +await page.expose_binding("clicked", print, handle=true) +await page.set_content(""" + +