kestra-io / kestra-io/plugin-selenium
Add Selenium plugin for browser automation
@Malaydewangan09 is already working on this.
Since Jun 1, 2026.
- Dominant language
- Java
- Stars
- 0
- Forks
- 0
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 2
Description
Add Selenium plugin for browser automation
Summary
Add a Selenium plugin so Kestra flows can drive a real browser: navigate pages, fill and
submit forms, click elements, wait for content, extract text, run JavaScript, capture
screenshots, and download files. It connects to a remote Selenium Grid over WebDriver, so
the browser runs in a container and the flow stays declarative.
This reaches data and actions that only exist inside a browser (sites with no API, content
rendered by JavaScript, multi-step web workflows), which no existing Kestra plugin can do.
Motivation
Today, anything that requires a browser falls outside Kestra. Users work around it with
hand-written Python/Selenium scripts in a Python task, external RPA tools, or manual work.
Common needs that have no API and no plugin:
- Scraping data from pages that render content with JavaScript.
- Filling and submitting forms in legacy systems or vendor portals that offer no API.
- End-to-end / synthetic monitoring of a login or checkout path.
- Downloading invoices, statements, and reports from portals behind a login.
A first-class task keeps these in the same flow as the upstream preparation, retries,
branching, and notifications, instead of a black-box script.
Plugin Structure
- Repository:
plugin-selenium(OSS, public) - Namespace:
io.kestra.plugin.selenium - Category:
TOOL - Reference model: scaffolded from
plugin-apifyconventions.
Scope (this issue)
One core task, Browse, that opens a single WebDriver session against a Selenium Grid,
runs an ordered list of actions in that session, then closes it. A session cannot span
multiple Kestra tasks (a live WebDriver is not serializable and tasks run independently),
so a single task with an actions list is the correct model for multi-step automation.
io.kestra.plugin.selenium.Browse
Connection properties (shared, on an AbstractSeleniumTask base):
remoteUrl(required): WebDriver / Grid endpoint, e.g.http://localhost:4444.browser:CHROME(default),FIREFOX, orEDGE.headless: defaulttrue.pageLoadTimeout: defaultPT30S.capabilities: extra browser capabilities merged into the options.
Actions (the action field on each list item):
NAVIGATE— go to a URL.CLICK— click an element by CSS selector.TYPE— type text into an element.WAIT_FOR— wait until an element is present (waitTimeout, defaultPT10S).EXTRACT_TEXT— read text from one element, or all matches whenmultiple: true.SCREENSHOT— capture the viewport, stored in Kestra internal storage.EXECUTE_SCRIPT— run JavaScript and capture the return value.DOWNLOAD— trigger and capture a file download. Uses Selenium 4 managed downloads
(se:downloadsEnabled+HasDownloads), so files that land on the grid node are
retrieved and stored in Kestra.
Outputs:
extracted(Map): texts fromEXTRACT_TEXT, keyed by actionidorextract_<index>.screenshots(Map): internal storage URIs, keyed by filename.scriptResults(Map): return values fromEXECUTE_SCRIPT.downloads(Map): internal storage URIs of downloaded files, keyed by filename.
Gradle Dependencies
// Selenium WebDriver Java client
implementation "org.seleniumhq.selenium:selenium-java:4.27.0"
Browser runtime for development and tests
Integration tests connect to a Selenium Grid over remoteUrl. On Apple Silicon the
multi-arch Chromium image is required (selenium/standalone-chromium, 4.21.0+). A
docker-compose-ci.yml starts the grid on port 4444 (and noVNC on 7900), with
SE_NODE_ENABLE_MANAGED_DOWNLOADS=true so the DOWNLOAD action works.
YAML Examples
Example 1 — Scrape headlines and capture a screenshot
id: selenium_scrape
namespace: company.web
tasks:
- id: browse
type: io.kestra.plugin.selenium.Browse
remoteUrl: "{{ secret('SELENIUM_GRID_URL') }}"
browser: CHROME
headless: true
actions:
- action: NAVIGATE
url: "https://news.ycombinator.com"
- action: WAIT_FOR
selector: ".titleline"
- action: EXTRACT_TEXT
id: headlines
selector: ".titleline > a"
multiple: true
- action: SCREENSHOT
name: frontpage.png
- id: log
type: io.kestra.plugin.core.log.Log
message: "Scraped {{ outputs.browse.extracted.headlines | length }} headlines"
Example 2 — Fill and submit a login form, read the result
id: form_login
namespace: company.web
inputs:
- id: username
type: STRING
tasks:
- id: login
type: io.kestra.plugin.selenium.Browse
remoteUrl: "{{ secret('SELENIUM_GRID_URL') }}"
actions:
- action: NAVIGATE
url: "https://the-internet.herokuapp.com/login"
- action: TYPE
selector: "#username"
value: "{{ inputs.username }}"
- action: TYPE
selector: "#password"
value: "{{ secret('APP_PASSWORD') }}"
- action: CLICK
selector: "button[type='submit']"
- action: WAIT_FOR
selector: "#flash"
- action: EXTRACT_TEXT
id: flash
selector: "#flash"
- id: log
type: io.kestra.plugin.core.log.Log
message: "{{ outputs.login.extracted.flash }}"
Example 3 — Download a file from a page and store it
id: selenium_download
namespace: company.ops
tasks:
- id: fetch
type: io.kestra.plugin.selenium.Browse
remoteUrl: "{{ secret('SELENIUM_GRID_URL') }}"
actions:
- action: NAVIGATE
url: "https://the-internet.herokuapp.com/download"
- action: WAIT_FOR
selector: ".example a"
- action: DOWNLOAD
selector: ".example a:first-of-type"
- id: log
type: io.kestra.plugin.core.log.Log
message: "Stored files: {{ outputs.fetch.downloads }}"
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.