Skip to main content

Rodney: Chrome automation from the command line

PyPI Changelog Tests License

A Go CLI tool that drives a persistent headless Chrome instance using the rod browser automation library. Each command connects to the same long-running Chrome process, making it easy to script multi-step browser interactions from shell scripts or interactive use.

Architecture

rodney start          →  launches Chrome (headless, persists after CLI exits)
                          saves WebSocket debug URL to ~/.rodney/state.json

rodney connect H:P    →  connects to an existing Chrome on a remote debug port
                          saves WebSocket debug URL to ~/.rodney/state.json

rodney open URL       →  connects to running Chrome via WebSocket
                          navigates the active tab, disconnects

rodney js EXPR        →  connects, evaluates JS, prints result, disconnects

rodney stop           →  connects and shuts down Chrome, cleans up state

Each CLI invocation is a short-lived process. Chrome runs independently and tabs persist between commands.

Building

go build -o rodney .

Requires:

  • Go 1.21+
  • Google Chrome or Chromium installed (or set ROD_CHROME_BIN=/path/to/chrome)

Usage

Start/stop the browser

rodney start              # Launch headless Chrome
rodney start --show       # Launch with visible browser window
rodney start --insecure   # Launch with TLS errors ignored (-k shorthand)
rodney connect host:9222  # Connect to existing Chrome on remote debug port
rodney status             # Show browser info and active page
rodney stop               # Shut down Chrome

Navigate

rodney open https://example.com    # Navigate to URL
rodney open example.com            # http:// prefix added automatically
rodney back                        # Go back
rodney forward                     # Go forward
rodney reload                      # Reload page
rodney reload --hard               # Reload bypassing cache
rodney clear-cache                 # Clear the browser cache

Extract information

rodney url                    # Print current URL
rodney title                  # Print page title
rodney text "h1"              # Print text content of element
rodney html "div.content"     # Print outer HTML of element
rodney html                   # Print full page HTML
rodney attr "a#link" href     # Print attribute value
rodney pdf output.pdf         # Save page as PDF

Run JavaScript

rodney js document.title                        # Evaluate expression
rodney js "1 + 2"                               # Math
rodney js 'document.querySelector("h1").textContent'  # DOM queries
rodney js '[1,2,3].map(x => x * 2)'            # Returns pretty-printed JSON
rodney js 'document.querySelectorAll("a").length'     # Count elements

The expression is automatically wrapped in () => { return (expr); }.

Interact with elements

rodney click "button#submit"       # Click element
rodney input "#search" "query"     # Type into input field
rodney clear "#search"             # Clear input field
rodney file "#upload" photo.png    # Set file on a file input
rodney file "#upload" -            # Set file from stdin
rodney download "a.pdf-link"       # Download href/src target to file
rodney download "a.pdf-link" -     # Download to stdout
rodney select "#dropdown" "value"  # Select dropdown by value
rodney submit "form#login"         # Submit a form
rodney hover ".menu-item"          # Hover over element
rodney focus "#email"              # Focus element

Wait for conditions

rodney wait ".loaded"       # Wait for element to appear and be visible
rodney waitload             # Wait for page load event
rodney waitstable           # Wait for DOM to stop changing
rodney waitidle             # Wait for network to be idle
rodney sleep 2.5            # Sleep for N seconds

Screenshots

rodney screenshot                         # Save as screenshot.png
rodney screenshot page.png                # Save to specific file
rodney screenshot -w 1280 -h 720 out.png  # Set viewport width/height
rodney screenshot-el ".chart" chart.png   # Screenshot specific element

Manage tabs

rodney pages                    # List all tabs (* marks active)
rodney newpage https://...      # Open URL in new tab
rodney page 1                   # Switch to tab by index
rodney closepage 1              # Close tab by index
rodney closepage                # Close active tab

Query elements

rodney exists ".loading"    # Exit 0 if exists, exit 1 if not
rodney count "li.item"      # Print number of matching elements
rodney visible "#modal"     # Exit 0 if visible, exit 1 if not
rodney assert 'document.title' 'Home'  # Exit 0 if equal, exit 1 if not
rodney assert 'document.querySelector("h1") !== null'  # Exit 0 if truthy

Accessibility testing

rodney ax-tree                           # Dump full accessibility tree
rodney ax-tree --depth 3                 # Limit tree depth
rodney ax-tree --json                    # Output as JSON

rodney ax-find --role button             # Find all buttons
rodney ax-find --name "Submit"           # Find by accessible name
rodney ax-find --role link --name "Home" # Combine filters
rodney ax-find --role button --json      # Output as JSON

rodney ax-node "#submit-btn"             # Inspect element's a11y properties
rodney ax-node "h1" --json               # Output as JSON

These commands use Chrome's Accessibility CDP domain to expose what assistive technologies see. ax-tree uses getFullAXTree, ax-find uses queryAXTree, and ax-node uses getPartialAXTree.

# CI check: verify all buttons have accessible names
rodney ax-find --role button --json | python3 -c "
import json, sys
buttons = json.load(sys.stdin)
unnamed = [b for b in buttons if not b.get('name', {}).get('value')]
if unnamed:
    print(f'FAIL: {len(unnamed)} button(s) missing accessible name')
    sys.exit(1)
print(f'PASS: all {len(buttons)} buttons have accessible names')
"

Directory-scoped sessions

By default, Rodney stores state globally in ~/.rodney/. You can instead create a session scoped to the current directory with --local:

rodney start --local          # State stored in ./.rodney/state.json
                              # Chrome data in ./.rodney/chrome-data/
rodney open https://example.com   # Auto-detects local session
rodney stop                       # Cleans up local session

This is useful when you want isolated browser sessions per project — each directory gets its own Chrome instance, cookies, and state.

Auto-detection: When neither --local nor --global is specified, Rodney checks for ./.rodney/state.json in the current directory. If found, it uses the local session; otherwise it falls back to the global ~/.rodney/ session.

# Force global even when a local session exists
rodney --global open https://example.com

# Force local (errors if no local session)
rodney --local status

The --local and --global flags can appear anywhere in the command:

rodney --local start
rodney start --local          # Same effect
rodney open --global https://example.com

Add .rodney/ to your .gitignore to keep session state out of version control.

Shell scripting examples

# Wait for page to load and extract data
rodney start
rodney open https://example.com
rodney waitstable
title=$(rodney title)
echo "Page: $title"

# Conditional logic based on element presence
if rodney exists ".error-message"; then
    rodney text ".error-message"
fi

# Loop through pages
for url in page1 page2 page3; do
    rodney open "https://example.com/$url"
    rodney waitstable
    rodney screenshot "${url}.png"
done

rodney stop

Exit codes

Rodney uses distinct exit codes to separate check failures from errors:

Exit code Meaning
0 Success
1 Check failed — the command ran successfully but the condition/assertion was not met
2 Error — something went wrong (bad arguments, no browser session, timeout, etc.)

This makes it easy to distinguish between "the assertion is false" and "the command couldn't run" in scripts and CI pipelines.

Using Rodney for checks

Several commands return exit code 1 when a condition is not met, making them useful as assertions in shell scripts and CI pipelines. All of these print their result to stdout and exit cleanly — no error message is written to stderr.

exists — check if an element exists in the DOM

rodney exists "h1"
# Prints "true", exits 0

rodney exists ".nonexistent"
# Prints "false", exits 1

visible — check if an element is visible

rodney visible "#modal"
# Prints "true" and exits 0 if the element exists and is visible

rodney visible "#hidden-div"
# Prints "false" and exits 1 if the element is hidden or doesn't exist

ax-find — check for accessibility nodes

rodney ax-find --role button --name "Submit"
# Prints the matching node(s), exits 0

rodney ax-find --role banner --name "Nonexistent"
# Prints "No matching nodes" to stderr, exits 1

assert — assert a JavaScript expression

With one argument, checks that the expression is truthy. With two arguments, checks that the expression's value equals the expected string. Use --message / -m to set a custom failure message.

# Truthy mode — check that expression evaluates to a truthy value
rodney assert 'document.querySelector(".logged-in") !== null'
# Prints "pass", exits 0

rodney assert 'document.querySelector(".nonexistent")'
# Prints "fail: got null", exits 1

# Equality mode — check that expression result matches expected value
rodney assert 'document.title' 'Dashboard'
# Prints "pass" if title is "Dashboard", exits 0

rodney assert 'document.querySelectorAll(".item").length' '3'
# Prints "pass" if there are exactly 3 items, exits 0

rodney assert 'document.title' 'Wrong Title'
# Prints 'fail: got "Dashboard", expected "Wrong Title"', exits 1

The expression is evaluated the same way as rodney js — the result is converted to its string representation before comparison. This means rodney assert 'document.title' 'Dashboard' compares the unquoted string, and rodney assert '1 + 2' '3' compares the number as a string.

Use --message (or -m) to add a human-readable description to the failure output:

rodney assert 'document.querySelector(".logged-in")' -m "User should be logged in"
# On failure: "fail: User should be logged in (got null)"

rodney assert 'document.title' 'Dashboard' --message "Wrong page loaded"
# On failure: 'fail: Wrong page loaded (got "Home", expected "Dashboard")'

Combining checks in a shell script

You can chain these together in a single script to run multiple assertions. Because check failures use exit code 1 while real errors use exit code 2, you can use set -e to abort on errors while handling check failures explicitly:

#!/bin/bash
set -euo pipefail

FAIL=0

check() {
    if ! "$@"; then
        echo "FAIL: $*"
        FAIL=1
    fi
}

rodney start
rodney open "https://example.com"
rodney waitstable

# Assert elements exist
check rodney exists "h1"
check rodney exists "nav"
check rodney exists "footer"

# Assert key elements are visible
check rodney visible "h1"
check rodney visible "#main-content"

# Assert JS expressions
check rodney assert 'document.title' 'Example Domain'
check rodney assert 'document.querySelectorAll("p").length' '2'
check rodney assert 'document.querySelector("h1") !== null'

# Assert accessibility requirements
check rodney ax-find --role navigation
check rodney ax-find --role heading --name "Example Domain"

rodney stop

if [ "$FAIL" -ne 0 ]; then
    echo "Some checks failed"
    exit 1
fi
echo "All checks passed"

This pattern is useful in CI — run Rodney as a post-deploy check, an accessibility audit, or a smoke test against a staging environment. Because exit code 2 signals an actual error (e.g. Chrome didn't start), set -e will abort the script immediately if something is broken rather than reporting a misleading test failure.

Configuration

Environment Variable Default Description
RODNEY_HOME ~/.rodney Data directory for state and Chrome profile
ROD_CHROME_BIN /usr/bin/google-chrome Path to Chrome/Chromium binary
ROD_TIMEOUT 30 Default timeout in seconds for element queries
HTTPS_PROXY / HTTP_PROXY (none) Authenticated proxy auto-detected on start

Global state is stored in ~/.rodney/state.json with Chrome user data in ~/.rodney/chrome-data/. When using --local, state is stored in ./.rodney/state.json and ./.rodney/chrome-data/ in the current directory instead. Set RODNEY_HOME to override the default global directory.

Proxy support

In environments with authenticated HTTP proxies (e.g., HTTPS_PROXY=http://user:pass@host:port), rodney start automatically:

  1. Detects the proxy credentials from environment variables
  2. Launches a local forwarding proxy that injects Proxy-Authorization headers into CONNECT requests
  3. Configures Chrome to use the local proxy

This is necessary because Chrome cannot natively authenticate to proxies during HTTPS tunnel (CONNECT) establishment. The local proxy runs as a background process and is automatically cleaned up by rodney stop.

See claude-code-chrome-proxy.md for detailed technical notes.

How it works

The tool uses the rod Go library which communicates with Chrome via the DevTools Protocol (CDP) over WebSocket. Key implementation details:

  • start uses rod's launcher package to start Chrome with Leakless(false) so Chrome survives after the CLI exits
  • Proxy auth handled via a local forwarding proxy that bridges Chrome to authenticated upstream proxies
  • State persistence via a JSON file containing the WebSocket debug URL and Chrome PID
  • Each command creates a new rod Browser connection to the same Chrome instance, executes the operation, and disconnects
  • Element queries use rod's built-in auto-wait with a configurable timeout (default 30s)
  • JS evaluation wraps user expressions in arrow functions as required by rod's Eval
  • Accessibility commands call CDP's Accessibility domain directly via rod's proto package (getFullAXTree, queryAXTree, getPartialAXTree)

Dependencies

Commands reference

Command Arguments Description
start [--show] [--insecure|-k] Launch Chrome (headless by default, --show for visible)
connect <host:port> Connect to existing Chrome on remote debug port
stop Shut down Chrome
status Show browser status
open <url> Navigate to URL
back Go back in history
forward Go forward in history
reload [--hard] Reload page (--hard bypasses cache)
clear-cache Clear the browser cache
url Print current URL
title Print page title
html [selector] Print HTML (page or element)
text <selector> Print element text content
attr <selector> <name> Print attribute value
pdf [file] Save page as PDF
js <expression> Evaluate JavaScript
click <selector> Click element
input <selector> <text> Type into input
clear <selector> Clear input
file <selector> <path|-> Set file on a file input (- for stdin)
download <selector> [file|-] Download href/src target (- for stdout)
select <selector> <value> Select dropdown value
submit <selector> Submit form
hover <selector> Hover over element
focus <selector> Focus element
wait <selector> Wait for element to appear
waitload Wait for page load
waitstable Wait for DOM stability
waitidle Wait for network idle
sleep <seconds> Sleep N seconds
screenshot [-w N] [-h N] [file] Page screenshot (optional viewport size)
screenshot-el <selector> [file] Element screenshot
pages List tabs
page <index> Switch tab
newpage [url] Open new tab
closepage [index] Close tab
exists <selector> Check element exists (exit 1 if not)
count <selector> Count matching elements
visible <selector> Check element visible (exit 1 if not)
assert <expr> [expected] [-m msg] Assert JS expression is truthy or equals expected (exit 1 if not)
ax-tree [--depth N] [--json] Dump accessibility tree
ax-find [--name N] [--role R] [--json] Find accessible nodes
ax-node <selector> [--json] Show element accessibility info

Global flags

Flag Description
--local Use directory-scoped session (./.rodney/)
--global Use global session (~/.rodney/)
--version Print version and exit
--help, -h, help Show help message

Metadata

Release files for rodney 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for rodney 0.4.0
File Actions
rodney-0.4.0-py3-none-win_arm64.whl Python 3 none Windows ARM64 Details for rodney-0.4.0-py3-none-win_arm64.whl
rodney-0.4.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details for rodney-0.4.0-py3-none-win_amd64.whl
rodney-0.4.0-py3-none-musllinux_1_2_x86_64.whl Python 3 none Linux musl 1.2+ x86-64 Details for rodney-0.4.0-py3-none-musllinux_1_2_x86_64.whl
rodney-0.4.0-py3-none-musllinux_1_2_aarch64.whl Python 3 none Linux musl 1.2+ ARM64 Details for rodney-0.4.0-py3-none-musllinux_1_2_aarch64.whl
rodney-0.4.0-py3-none-manylinux_2_17_x86_64.whl Python 3 none Linux glibc 2.17+ x86-64 Details for rodney-0.4.0-py3-none-manylinux_2_17_x86_64.whl
rodney-0.4.0-py3-none-manylinux_2_17_aarch64.whl Python 3 none Linux glibc 2.17+ ARM64 Details for rodney-0.4.0-py3-none-manylinux_2_17_aarch64.whl
rodney-0.4.0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details for rodney-0.4.0-py3-none-macosx_11_0_arm64.whl
rodney-0.4.0-py3-none-macosx_10_9_x86_64.whl Python 3 none macOS 10.9+ x86-64 Details for rodney-0.4.0-py3-none-macosx_10_9_x86_64.whl

Total release size: 89.1 MB

Release files / rodney-0.4.0-py3-none-win_arm64.whl

Download URL rodney-0.4.0-py3-none-win_arm64.whl
Size 9.9 MB
Tags Python 3 Windows ARM64
SHA-256 checksum
How to use checksums
524bf8ec5548ef4c859c99f5f0d056dd38e74539ae65efff04f7a23963850b07
BLAKE2b-256 checksum
How to use checksums
18dbbffb283af3be3fa45c8d8332757d0adb58d9b6333209f07bb20f86b5fa23
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Feb 17, 2026.

Transparency log

Release files / rodney-0.4.0-py3-none-win_amd64.whl

Download URL rodney-0.4.0-py3-none-win_amd64.whl
Size 10.5 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
8ae4d429c3de7f938af9a851dd90b9fd4c831fb8e49b906ac941effead130d05
BLAKE2b-256 checksum
How to use checksums
430f1fbc12c3b7ce6abb70e26e078f84da30b5ca833d198ef4af575e8e7fec10
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Feb 17, 2026.

Transparency log

Release files / rodney-0.4.0-py3-none-musllinux_1_2_x86_64.whl

Download URL rodney-0.4.0-py3-none-musllinux_1_2_x86_64.whl
Size 11.5 MB
Tags Linux musl 1.2+ x86-64 Python 3
SHA-256 checksum
How to use checksums
4927959cd8d6a4768654336e5320ac41f82a554de1253304459d3d40df4679c2
BLAKE2b-256 checksum
How to use checksums
1b526251ce66777523f8d08aac06c2668e9d1aae4334bf66f41a0e71bfe8cd76
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Feb 17, 2026.

Transparency log

Release files / rodney-0.4.0-py3-none-musllinux_1_2_aarch64.whl

Download URL rodney-0.4.0-py3-none-musllinux_1_2_aarch64.whl
Size 11.1 MB
Tags Linux musl 1.2+ ARM64 Python 3
SHA-256 checksum
How to use checksums
b009bd05d165b4cc41cba4688267dd0fb62d0bfcc53fe925f15d324fccde5917
BLAKE2b-256 checksum
How to use checksums
a860d90b1c803c4f87459d5a2e7f7bb225e25c3ffa732123a84cae17515d74c5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Feb 17, 2026.

Transparency log

Release files / rodney-0.4.0-py3-none-manylinux_2_17_x86_64.whl

Download URL rodney-0.4.0-py3-none-manylinux_2_17_x86_64.whl
Size 11.5 MB
Tags Linux glibc 2.17+ x86-64 Python 3
SHA-256 checksum
How to use checksums
5d34528bf63f44029f9a571176bd59fbd8b0e51cd8430befbdae07ef3b9d4194
BLAKE2b-256 checksum
How to use checksums
7f296e6cf566571353f90bce0a9027e43277c22ea2617df906c1cda51d4be08e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Feb 17, 2026.

Transparency log

Release files / rodney-0.4.0-py3-none-manylinux_2_17_aarch64.whl

Download URL rodney-0.4.0-py3-none-manylinux_2_17_aarch64.whl
Size 11.1 MB
Tags Linux glibc 2.17+ ARM64 Python 3
SHA-256 checksum
How to use checksums
c74ba09b82d46458abe21111bc324f02a3d61594fb289e10de59e00315d6ea26
BLAKE2b-256 checksum
How to use checksums
71f29c01e9e99c45a1d5abbb9561cf472ff320ca3c9985c92e10f40e0329cc59
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Feb 17, 2026.

Transparency log

Release files / rodney-0.4.0-py3-none-macosx_11_0_arm64.whl

Download URL rodney-0.4.0-py3-none-macosx_11_0_arm64.whl
Size 11.6 MB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
d3c0831ed8a029f23f19da9175a20082619eeeed344b56d71a3650de1e54f794
BLAKE2b-256 checksum
How to use checksums
1e47448e940e44f36058b5b9d8b06c8ed8719680f7fcf8ecc90beeefe47277dc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Feb 17, 2026.

Transparency log

Release files / rodney-0.4.0-py3-none-macosx_10_9_x86_64.whl

Download URL rodney-0.4.0-py3-none-macosx_10_9_x86_64.whl
Size 11.9 MB
Tags Python 3 macOS 10.9+ x86-64
SHA-256 checksum
How to use checksums
7b351394f80960cb903df07994b5a4956cee08246c2dfc4c9e2c637a8cab3b79
BLAKE2b-256 checksum
How to use checksums
0cd861fb75202eb13a89bf51c3978c8f82d5a04250d1e626da764a8c6b03dd1a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Feb 17, 2026.

Transparency log

Security for rodney 0.4.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 8 files in this release have been uploaded with provenance metadata.

Select from 8 files

Attestation for rodney-0.4.0-py3-none-win_arm64.whl

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Feb 17, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page