Skip to main content
This cookbook extracts two datasets from OpenEMR, an open-source EHR, using the public demo at https://demo.openemr.io/openemr/index.php:
  1. Patient demographics from Patient/Client > Finder
  2. Encounter billing data from Reports > Visits > Superbill
Demo credentials: admin / pass (resets daily at 8:00 AM UTC)

Prerequisites

pip install skyvern

Why a single task isn’t enough

A basic task pointed at OpenEMR with a vague prompt will partially work, but hits four problems in production:
result = await client.run_task(
    url="https://demo.openemr.io/openemr/index.php",
    prompt="Log in and extract the patient list",
)
ProblemImpact
No proxyProduction EHR portals sit behind WAFs that block datacenter IPs
Login every runWastes steps, fragile with session complexity
Vague navigationOpenEMR uses iframes and dynamic menus — needs explicit goals
No paginationOnly gets page 1 of multi-page results
The sections below solve each one.

Residential proxies

Route the browser through a residential IP to bypass WAF/bot detection. The demo works without one, but production portals require it.
In the run panel, expand Advanced Settings and set Proxy Location to a country (e.g., United States).
See Proxy & Geolocation for all available locations.

Browser profiles

Log in once, save the browser state as a profile, and skip login on future runs.
1

Create a login workflow

Go to Workflows in the sidebar and create a new workflow. Add a Navigation block with URL https://demo.openemr.io/openemr/index.php and goal: “Log in with username ‘admin’ and password ‘pass’. Confirm the Calendar page loads.”On the Start node, expand the settings and enable Save & Reuse Session. Set Proxy Location to a country (e.g., United States).
2

Run the workflow

Run the workflow and wait for it to complete.
3

Create a profile via API

Browser profile creation is done via the API. Use the create_browser_profile call from the API/SDK tab with the completed workflow run ID. Name it openemr-demo-admin.
persist_browser_session is a workflow definition property — set it when creating the workflow, not when running it. See Browser Profiles for the full lifecycle.

Extract patient demographics

Navigate to Patient/Client > Finder and extract the results table.
Create a workflow with two blocks:
  1. Navigation block — URL: https://demo.openemr.io/openemr/index.php. Goal: “Click Patient/Client in the top menu, then click Finder. Click Search to display all patients.”
  2. Extraction block — Goal: “Extract all patient rows from the Patient Finder results table.” Paste the patient schema into Data Schema.
On the Start node, set Proxy Location to a country (e.g., United States). Run the workflow.
Example output:
{
  "patients": [
    { "name": "Belford, Phil", "pid": "1", "dob": "1972-02-09", "phone_home": "333-444-2222" },
    { "name": "Underwood, Susan Ardmore", "pid": "2", "dob": "1967-02-08", "phone_home": "4443332222" },
    { "name": "Moore, Wanda", "pid": "3", "dob": "2007-02-18", "phone_home": null }
  ]
}
The demo resets daily and community users add test patients, so exact records may differ.
Browser profiles cannot be used directly with standalone tasks. Create a browser session from the profile first, then pass the session ID. See Pagination with browser sessions below for the full pattern.

Extract encounter billing data

Navigate to Reports > Visits > Superbill, set a date range, and extract the report.
Create a workflow with two blocks:
  1. Navigation block — Goal: “Click Reports in the top menu, then Visits, then Superbill. Set the From date to 2020-01-01 and the To date to today. Click Submit.”
  2. Extraction block — Goal: “Extract all encounter rows from the Superbill report.” Paste the encounter schema into Data Schema.
On the Start node, set Proxy Location to a country (e.g., United States). Run the workflow.
Example output:
{
  "encounters": [
    {
      "patient_name": "Phil Lopez",
      "encounter_date": "2024-06-01",
      "provider": "Administrator Administrator",
      "billing_code": "99213",
      "code_description": "Office/outpatient visit, est patient, low complexity",
      "charge": 50.00
    }
  ]
}

Pagination with browser sessions

A Browser Profile is a saved snapshot. A Browser Session is a live browser instance that persists between tasks. Use sessions to paginate: extract page 1, click Next, extract page 2.
1

Create a session

Go to Browsers in the sidebar. Click Create Session. Set Proxy Location to a country (e.g., United States) and configure the timeout.
2

Navigate and extract page 1

Run a task against the session: “Click Patient/Client > Finder. Click Search. Extract all patient rows.”
3

Extract subsequent pages

Run another task against the same session: “Click Next to go to the next page. Extract all patient rows.” Repeat until no more results.
You cannot use browser_profile_id and browser_session_id in the same request. Use the profile to create the session, then pass only the session ID to tasks.

Error handling

OpenEMR can timeout or show session-expired pages. Use error_code_mapping on workflow blocks to classify failures, and max_retries to retry automatically.
On each Navigation and Extraction block, expand Advanced Settings and enable Error Messages. Add this JSON:
{ "session_expired": "Session expired, login required, or access denied page" }
max_retries is only available via the API. In the Cloud UI, Skyvern uses its default retry behavior. For fine-grained retry control, use the API/SDK approach.
See Error Handling and CAPTCHA & Bot Detection for more.

Complete workflow

This workflow combines everything: navigate to the Patient Finder, extract demographics, navigate to Superbill, and extract billing data — with error recovery and residential proxy.
1

Create the workflow

Go to Workflows and create a new workflow named “OpenEMR Daily Extract.” On the Start node, enable Save & Reuse Session and set Proxy Location to a country (e.g., United States).
2

Block 1: Navigation — open Patient Finder

Add a Navigation block. Set URL to https://demo.openemr.io/openemr/index.php and goal: “Click Patient/Client > Finder. Click Search to display all patients. If a login page appears, log in with ‘admin’/‘pass’.” In Advanced Settings, enable Error Messages and add {"session_expired": "Session expired, login required, or access denied page"}.
3

Block 2: Extraction — patient demographics

Add an Extraction block. Set goal: “Extract all patient rows from the Patient Finder results table.” Paste the patient schema into Data Schema.
4

Block 3: Navigation — open Superbill

Add another Navigation block. Set goal: “Click Reports > Visits > Superbill. Set From to 2020-01-01, To to today. Click Submit.” Add the same error messages mapping.
5

Block 4: Extraction — encounter billing

Add another Extraction block. Set goal: “Extract all encounter rows from the Superbill report.” Paste the encounter schema into Data Schema.
6

Run

Click Run. The workflow navigates to the Patient Finder, extracts demographics, then navigates to Superbill and extracts billing data.
For multi-page results, combine with the pagination pattern above.
TechniquePurpose
Residential proxyBypass WAF/bot detection
Browser profileSkip login on every run
Navigation goalsExplicit menu clicks for iframe-based UI
JSON schemasConsistent, structured output
Session reusePaginate multi-page results
Error mapping + retriesRecover from session timeouts
The OpenEMR demo resets daily at 8:00 AM UTC, so profiles expire every day. In production, re-run your login workflow weekly or whenever extractions fail with auth errors. See Browser Profiles for the refresh pattern.

Resources

Browser Profiles

Full lifecycle: create, refresh, and delete saved browser state

Proxy & Geolocation

All proxy locations and country-specific routing options

Credential Management

Securely store and use login credentials

Error Handling

Error code mapping, failure classification, and retry strategies

Extract Structured Data

JSON schema design and the interactive schema builder