Write a NopeCHA API key into an unpacked Automation Build (chromium_automation.zip).
The Automation Build reads its key from the Nopecha Manifest Config, manifest["nopecha"]["key"] in manifest.json. This package sets that field, turns on every captcha *_auto_solve and *_auto_open flag, and sets enabled to true. It leaves the rest of the Nopecha Manifest Config alone, including delay times and selectors, and it never rewrites the top-level "key" (the Chrome extension public key). It does not modify JavaScript or HTML, and it does not download the Web Store CRX.
If you omit extension_path, load() downloads chromium_automation.zip from NopeCHA GitHub releases into extensions/NopeCHA and re-downloads when manifest["version_name"] differs from the latest release tag. Pass version="0.6.1" to pin a tag. A user-supplied Extension Directory is never overwritten by a download.
The API key stays in the process. load() does not call chrome_extension_python's storage writer, so the key is not saved in site-packages/chrome_extension_python/package_storage.json.
- Python 3.8 or newer.
- One browser driver, installed separately, depending on how you launch Chrome: Botasaurus (
pip install botasaurus), Selenium (pip install selenium), or Playwright (pip install playwright && playwright install chromium).
The package is published on PyPI:
pip install nopecha-extensionextension_path is the unpacked Automation Build directory — the folder that directly contains manifest.json. To get one, download chromium_automation.zip from NopeCHA GitHub releases and unzip it:
curl -LO https://github.com/NopeCHALLC/nopecha-extension/releases/latest/download/chromium_automation.zip
unzip chromium_automation.zip -d path/to/chromium_automationupdate_files() rewrites manifest.json when the API key differs or any captcha type is still disabled. A second call with the same key and all captcha types already enabled leaves the file unchanged and reports it under skipped.
import os
from nopecha_extension import Nopecha
ext = Nopecha(
api_key=os.environ["NOPECHA_API_KEY"],
extension_path="path/to/chromium_automation",
)
report = ext.update_files()
print(report)A changed key produces:
{
"modified": [
"manifest.json"
],
"skipped": [],
"errors": []
}An empty string, a whitespace-only string, None, or any non-string raises ValueError (api_key must be a non-empty string) before the file is opened for writing.
Passing the Nopecha instance in extensions makes Botasaurus call load(), which downloads the Automation Build if needed, patches manifest.json, and returns Chrome's --load-extension flag. load() raises FileNotFoundError when a user-supplied Extension Directory has no manifest.json.
import os
from botasaurus.browser import Driver, browser
from nopecha_extension import Nopecha
ext = Nopecha(api_key=os.environ["NOPECHA_API_KEY"])
@browser(extensions=[ext])
def open_example(driver: Driver, data):
driver.get("https://example.com/")
driver.prompt()
if __name__ == "__main__":
open_example()Point extension_path at an unpacked Automation Build to skip the download. load(with_command_line_option=False) returns the Extension Directory path instead of the flag.
Pass the flag from load() to Chrome options:
import os
from selenium import webdriver
from nopecha_extension import Nopecha
ext = Nopecha(api_key=os.environ["NOPECHA_API_KEY"])
options = webdriver.ChromeOptions()
options.add_argument(ext.load())
driver = webdriver.Chrome(options=options)
driver.get("https://example.com/")Chromium loads extensions only in a persistent context launched in headful mode:
import os
from playwright.sync_api import sync_playwright
from nopecha_extension import Nopecha
ext = Nopecha(api_key=os.environ["NOPECHA_API_KEY"])
extension_dir = ext.load(with_command_line_option=False)
with sync_playwright() as p:
context = p.chromium.launch_persistent_context(
"",
channel="chromium",
headless=False,
args=[
f"--disable-extensions-except={extension_dir}",
f"--load-extension={extension_dir}",
],
)
page = context.new_page()
page.goto("https://example.com/")The key is read from the environment or stdin, never from a positional argument. The default is a dry run: nothing is written unless --write is passed. --key-env defaults to NOPECHA_API_KEY.
export NOPECHA_API_KEY="YOUR_NOPECHA_KEY"
python -m nopecha_extension.patcher path/to/chromium_automation
python -m nopecha_extension.patcher path/to/chromium_automation --write
python -m nopecha_extension.patcher path/to/chromium_automation --key-env NOPECHA_API_KEY --write
printf '%s\n' "$NOPECHA_API_KEY" | python -m nopecha_extension.patcher path/to/chromium_automation --key-stdin --writeA missing environment variable prints Environment variable NOPECHA_API_KEY is not set to stderr and exits with status 2. The manifest is not changed.
ValueError: api_key must be a non-empty string— the key isNone, empty, or whitespace. Export a real key (export NOPECHA_API_KEY="...") before constructingNopecha.FileNotFoundErrorfromload()— the Extension Directory you supplied has nomanifest.json. Pointextension_pathat the folder that directly containsmanifest.json; unzipping sometimes creates a nested folder.- The extension does not load in headless Chrome — Chromium's old headless mode ignores extensions. Run headful (drop
--headlessin Selenium, useheadless=Falsein Playwright). - The Automation Build download fails —
load()withoutextension_pathfetches the zip from GitHub releases, which requires network access togithub.com. Downloadchromium_automation.zipmanually, unzip it as shown above, and passextension_pathinstead. - The key is written but captchas are not solved — confirm
manifest["nopecha"]["key"]in the Extension Directory'smanifest.jsonholds your key, confirm the extension appears atchrome://extensions, and confirm the key is active on your NopeCHA dashboard. This package only writes the Nopecha Manifest Config; solving runs on NopeCHA's servers.
This package only edits local extension configuration. NopeCHA's terms of service still apply to your API key and usage, and the terms of any site you automate still apply to that site. Automate only sites you are authorized to test.