Skip to main content
Read the Notte skill and follow its setup instructions when setting up Notte or building browser automation. This is the shared source for CLI setup, authentication, and the browser-to-code workflow.
Use POST /scrape to extract structured data, then save it to MySQL. This example extracts a page title and description and keeps one row per URL. Each successful run updates that row. Choose where the job runs:
  • Notte hosts the schedule and scrape: a Function runs hourly and sends the result to a small HTTPS endpoint in your application, which writes to MySQL.
  • Your server runs the whole job: a Python script scrapes and writes directly to MySQL, scheduled with cron.
Hosted Functions do not currently include a MySQL driver. The direct MySQL script below runs on your server, not in the hosted Function runtime. The hosted option uses HTTPS for database delivery.

1. Prepare MySQL

Use Python 3.11+ and a Notte API key. On the server that connects to MySQL, install requests, pydantic, and PyMySQL:
Create this table in your database:
Configure these environment variables on that server using your secret manager or deployment settings: Use a MySQL server/account that requires TLS. Allow connections from the machine running the writer. The script verifies the server certificate and hostname.

2. Save the scripts

Save this first file as scrape_function.py. Its scrape_page() helper calls the simple scrape endpoint; run() is the entry point for the hosted option.
scrape_function.py
response_format defines the fields to extract. Change PageData, the instructions, and the destination columns together to collect different data. HTTP errors and unsuccessful structured extraction raise an exception before a database write. Save the writer as scrape_to_mysql.py in the same directory:
scrape_to_mysql.py
Values are passed as SQL parameters. The binary URL comparison keeps case-sensitive paths distinct. The primary key and upsert prevent repeated runs from adding duplicate rows for the same URL. A failed write closes the connection without committing. scraped_at records the last successful write in UTC.

Option A: Run hourly as a hosted Function

Add an HTTPS receiver

If you already have a backend, add an authenticated endpoint that calls save_page(). Here is a minimal FastAPI receiver. Save it as mysql_receiver.py, alongside the two files above:
mysql_receiver.py
Install fastapi and uvicorn, set a strong random MYSQL_INGEST_TOKEN on the receiver, and deploy it behind HTTPS using your normal application hosting. For local development, start it with uvicorn mysql_receiver:app --host 127.0.0.1 --port 8000. Hosted Functions must use its publicly reachable HTTPS URL, for example https://your-app.example/ingest, not localhost. The receiver needs the MySQL variables from step 1. It does not need a Notte API key: the Function performs the scrape. Keep the endpoint authenticated; it can write to your database.

Deploy and test the Function

In the Console, open Settings > Function Secrets and add:
  • MYSQL_INGEST_URL: your receiver’s HTTPS URL, including /ingest.
  • MYSQL_INGEST_TOKEN: the same token configured on the receiver.
The Function reads these variables through Pydantic’s environment settings. You do not need to add your MySQL credentials to Notte. Notte supplies its own API key to the Function at run time. Install notte-sdk locally and set NOTTE_API_KEY, then deploy only scrape_function.py:
deploy_function.py
Run this once before scheduling. Confirm the result is {"url": "https://example.com", "saved": true} and check the saved row:

Enable the hourly schedule

Open the Function in the Console, select its Schedule tab, and use rate(1 hour). Set its variables to {"url": "https://example.com"}. The Function now scrapes and sends the result to your receiver hourly. Check the Function’s run history for failures. A failed scrape or receiver request fails the run; it does not report a successful database write. See Function schedules to pause or remove the schedule and Function management to inspect runs.

Option B: Connect directly from your server

Keep scrape_function.py and scrape_to_mysql.py together. Set NOTTE_API_KEY and the MySQL variables on your server. The ingest URL and token are not needed for this option. Run python scrape_to_mysql.py, then use the SQL query above to verify the saved row. Running it again should update the row rather than create a second one. To run hourly with Unix cron, use your actual directory and Python environment paths:
Make the required variables available to the cron process through your server’s environment configuration or a private wrapper script. Cron does not inherit your interactive shell’s environment. Keep credentials out of the crontab and source control, and check the log for failures.