Overview

Creating Functions

Write and deploy browser automation Functions

Writing a Function#

Functions are Python scripts with a run() function that serves as the entry point.

Basic Function#

def run():
    """A simple function that returns a greeting."""
    return "Hello from Notte Functions!"

Function with Parameters#

def run(name: str, greeting: str = "Hello"):
    """
    Greet someone by name.
    """
    return f"{greeting}, {name}!"

Browser Automation Function#

from notte_sdk import NotteClient
 
def run(url: str, selector: str):
    """
    Scrape data from a website.
    """
    client = NotteClient()
 
    with client.Session() as session:
        session.execute(type="goto", url=url)
        data = session.scrape(instructions=f"Extract content from {selector}")
 
    return {"url": url, "data": data}

Deploying Functions#

from notte_sdk import NotteClient
 
client = NotteClient()
 
function = client.Function(
    path="my_function.py",
    name="My Function",  # Display name
    description="What this function does",
    shared=False,  # Private by default
)

Parameters: workflow_path (str, required) — path to your Python file. name (str, optional) — display name. description (str, optional). shared (bool, default=False) — whether function is publicly accessible.

Function Requirements#

The Handler#

Must have a run() function (any other name is not picked up).

Dependencies#

Available packages: notte-sdk, requests, pydantic, the standard library, and most common packages.

Return Values#

Return JSON-serializable data only — strings, numbers, dicts, lists, None. Types like datetime or functions are not serializable directly.

Parameter Types#

def run(
    text: str,
    number: int,
    decimal: float,
    flag: bool,
    items: list,
    data: dict,
    optional: str | None = None,
    with_default: int = 10,
):
    pass

Use Pydantic models for structured, validated parameters:

from pydantic import BaseModel
 
class SearchParams(BaseModel):
    url: str
    query: str
    max_results: int = 10
 
def run(params: SearchParams):
    client = NotteClient()
    # Use params.url, params.query, etc.

Environment Variables#

import os
from notte_sdk import NotteClient
 
def run():
    api_key = os.getenv("MY_API_KEY")
    if not api_key:
        return {"error": "API key not configured"}
 
    client = NotteClient(api_key=api_key)

Set environment variables in the Console or locally for testing.

Error Handling#

def run(url: str):
    try:
        client = NotteClient()
        with client.Session() as session:
            session.execute(type="goto", url=url)
            data = session.scrape()
        return {"success": True, "data": data}
    except Exception as e:
        return {"success": False, "error": str(e), "error_type": type(e).__name__}

Let Functions fail explicitly when the caller passes bad input:

def run(url: str):
    if not url.startswith("https://"):
        raise ValueError("URL must use HTTPS")

Testing Locally#

def run(url: str, selector: str) -> dict:
    return {"url": url, "selector": selector}
 
result = run(url="https://example.com", selector=".content")
print(result)

Best Practices#

1. Document Parameters#

Use clear docstrings describing every argument and the return shape.

2. Return Structured Data#

Use consistent return formats across every Function, including a success flag and a timestamp.

3. Add Logging#

Log key steps (session start, navigation complete, item count extracted) for debugging.

4. Set Timeouts#

with client.Session(idle_timeout_minutes=5) as session:
    session.execute(type="goto", url=url)

5. Validate Inputs#

def run(url: str, count: int):
    if not url.startswith("http"):
        return {"error": "Invalid URL format"}
    if count < 1 or count > 100:
        return {"error": "Count must be between 1 and 100"}

Examples#

Form Submission#

from notte_sdk import NotteClient
 
def run(form_url: str, name: str, email: str, message: str):
    """Submit a contact form."""
    client = NotteClient()
 
    with client.Session() as session:
        session.execute(type="goto", url=form_url)
        session.execute(type="fill", id="name", value=name)
        session.execute(type="fill", id="email", value=email)
        session.execute(type="fill", id="message", value=message)
        session.execute(type="click", selector="button[type='submit']")
 
    return {"status": "submitted"}

Data Extraction#

from notte_sdk import NotteClient
from pydantic import BaseModel
 
class Product(BaseModel):
    name: str
    price: float
    in_stock: bool
 
def run(product_url: str):
    """Extract structured product data."""
    client = NotteClient()
 
    with client.Session() as session:
        session.execute(type="goto", url=product_url)
        product = session.scrape(response_format=Product, instructions="Extract product details")
 
    return product.model_dump()

Next Steps#


Back to overview

Updated

Was this page helpful?