Skip to main content
python_script_action lets you run arbitrary Python code against the live Playwright page object—covering anything that standard interaction actions cannot express.

Overview

  • Use when: Built-in actions are insufficient (complex DOM manipulation, custom scrolling, dispatching browser events, reading element properties).
  • Execution: The runner execs your script, finds an async function named code_fn, and calls it with the current Playwright page.
  • No output: This action does not return or store data. To extract data with custom code, use extraction_action.python_script.

Properties

PropertyTypeDescription
execution_codestrPython source that defines an async code_fn(page)

Script Contract

Your script must define an async function named code_fn that accepts a single page argument (a Playwright Page):
async def code_fn(page):
    # interact with the page here
The function is called as await code_fn(page). Any return value is ignored.

JSON Example

{
  "type": "action_node",
  "python_script_action": {
    "execution_code": "async def code_fn(page):\n    await page.evaluate(\"window.scrollTo(0, document.body.scrollHeight)\")"
  }
}

Common Patterns

Scroll to the bottom of the page

async def code_fn(page):
    await page.evaluate("window.scrollTo(0, document.body.scrollHeight)")

Wait for a custom JavaScript condition

async def code_fn(page):
    await page.wait_for_function("() => document.readyState === 'complete'")

Dispatch a custom browser event

async def code_fn(page):
    await page.evaluate("""
        document.querySelector('#upload-input').dispatchEvent(
            new Event('change', { bubbles: true })
        )
    """)

Interact with a shadow DOM element

async def code_fn(page):
    await page.evaluate("""
        document.querySelector('my-component').shadowRoot
            .querySelector('button.confirm')
            .click()
    """)
execution_code is evaluated with exec(). Only run scripts from trusted sources.

Python Script Extraction

To extract data from the page using custom code, use python_script inside an extraction_action instead. The contract is different: the function receives (axtree, browser) and must return a dict containing the extracted values.
{
  "type": "action_node",
  "extraction_action": {
    "python_script": {
      "script": "async def code_fn(axtree, browser):\n    page = await browser.get_current_page()\n    text = await page.locator('.order-id').inner_text()\n    return {\"order_id\": text.strip()}",
      "output_variable_names": ["order_id"]
    }
  }
}

Properties

PropertyTypeDefaultDescription
scriptstrRequiredPython source defining async def code_fn(axtree, browser)
extraction_formatdict | NoneNoneExpected output structure (required when output_variable_names is set)
output_variable_nameslist[str] | NoneNonePromote returned dict keys to generated_variables

Script Contract

async def code_fn(axtree, browser):
    # axtree: string representation of the page accessibility tree
    # browser: the Browser instance (use browser.get_current_page() for the Playwright page)
    return {"key": "value"}  # must return a dict
The returned dict is stored as OutputData and, if output_variable_names is set, the specified keys are promoted to generated_variables for use in later nodes.
All keys in output_variable_names must exist in extraction_format, or schema validation will fail.

Action vs Extraction — Which to Use

ScenarioUse
Scroll, dispatch events, manipulate DOMpython_script_action
Extract and store data from the pageextraction_action.python_script
Simple text / table extractionextraction_action.llm