Skip to main content

selenodriver

Selenium-style synchronous WebDriver API powered by Python nodriver.

selenodriver는 기존 Selenium 코드 스타일을 최대한 유지하면서, 내부 동작은 nodriver와 CDP 기반으로 처리하는 호환 레이어입니다.

selenodriver is a compatibility layer that preserves familiar Selenium coding patterns while using nodriver and CDP internally.

문서 / Documentation: 한국어 가이드 | English guide

목차 / Contents

핵심 강점 / Key Features

  • Selenium과 비슷한 동기 API: await 없이 driver.get(), find_element(), element.click() 형태로 사용합니다.
  • CDP 기반 마우스 클릭: 기본 element.click()은 JS el.click()이 아니라 화면 좌표를 계산해서 Input.dispatchMouseEvent를 보냅니다.
  • 입력 방식 분리: 마우스 클릭, 터치 클릭, JS 클릭을 명확히 나눠서 사용할 수 있습니다.
  • 좌표 기반 제어: element 중앙 클릭뿐 아니라 offset 클릭, 특정 좌표 클릭, element 내부 랜덤 위치 클릭을 지원합니다.
  • 모바일 흐름 지원: 터치 클릭, 터치 스크롤, 더블 탭, 롱 프레스, 터치 드래그, 모바일 에뮬레이션 확장을 제공합니다.
  • Selenium 호환 import: selenodriver.webdriver.* 경로를 지원해 기존 Selenium 코드와 비슷한 구조로 옮기기 쉽습니다.
  • 확장 모듈 구조: 외부/private extension을 붙여 브라우저 시작, 이동, 새 탭, context 변경 시점에 자동 로직을 적용할 수 있습니다.

English summary:

  • Synchronous Selenium-style API: use driver.get(), find_element(), and element.click() without await.
  • CDP mouse input: the default click calculates viewport coordinates and dispatches Input.dispatchMouseEvent instead of calling JavaScript el.click().
  • Explicit input modes: mouse, touch, and JavaScript clicks are separate operations.
  • Coordinate control: center, offset, absolute, and randomized in-element clicks are supported.
  • Mobile workflows: touch clicks, scrolling, double tap, long press, touch drag, and mobile emulation are included.
  • Migration-friendly imports: Selenium-like modules are available under selenodriver.webdriver.*.
  • Extension hooks: external or private modules can react to browser attach, navigation, tab discovery, and context changes.

버전과 의존성 / Version and Dependencies

현재 패키지 버전 / Current package version:

selenodriver 0.1.1

실행 요구사항 / Runtime requirements:

Python >= 3.10
nodriver >= 0.39

nodriver is declared as a package dependency in pyproject.toml, so package installers will install it automatically when installing selenodriver.

dependencies = [
  "nodriver>=0.39",
]

빠른 시작 / Quick Start

from selenodriver import ActionChains, By, Chrome, Keys, Options
from selenodriver.support import expected_conditions as EC
from selenodriver.support.ui import WebDriverWait

options = Options()
options.add_argument("--no-first-run")

driver = Chrome(headless=True, options=options)
driver.get("https://example.com")

heading = WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.TAG_NAME, "h1"))
)
print(heading.text)

ActionChains(driver).move_to_element(heading).click().send_keys(Keys.ENTER).perform()

driver.quit()

클릭과 입력 방식 / Click and Input Modes

selenodriver는 클릭 방식을 의도적으로 분리합니다.

selenodriver intentionally exposes each click mechanism separately.

방식 / Mode 사용 예 / API 내부 동작 / Implementation 용도 / Use case
기본/마우스 클릭 / Default mouse element.click() CDP Input.dispatchMouseEvent 일반 데스크톱 클릭 / Desktop interaction
명시적 마우스 클릭 / Explicit mouse element.mouse_click() CDP mousePressed / mouseReleased 기본 클릭과 동일 / Explicit mouse control
터치 클릭 / Touch element.touch_click() CDP Input.dispatchTouchEvent 모바일 탭 / Mobile tap behavior
JS 클릭 / JavaScript element.js_click() JS el.click() DOM 직접 호출 / Direct DOM activation

기본 클릭은 element의 화면상 중앙 좌표를 기준으로 마우스 이벤트를 보냅니다. JS 클릭이 필요한 경우에는 js_click()을 별도로 호출합니다.

The default click sends mouse events to the element's visual center. Call js_click() explicitly when direct DOM activation is required.

좌표 클릭 / 랜덤 위치 클릭 / Offset and Randomized Clicks

Selenium의 ActionChains 스타일로 element 중앙이 아닌 지점을 클릭할 수 있습니다.

Selenium-style ActionChains can click a point away from the element center.

from selenodriver import ActionChains

ActionChains(driver) \
    .move_to_element_with_offset(element, xoffset, yoffset) \
    .click() \
    .perform()

xoffset, yoffset은 Selenium 호환 기준으로 element의 중앙점 기준입니다.

For Selenium compatibility, xoffset and yoffset are measured from the element center.

element 내부의 랜덤 위치를 클릭하려면 좌상단 기준 랜덤 좌표를 만든 뒤 중앙점 기준 offset으로 변환합니다.

To click a randomized point inside an element, generate top-left-relative coordinates and convert them to center-relative offsets.

import random
from selenodriver import ActionChains

size = element.size
rx = random.randint(5, int(size["width"]) - 5)
ry = random.randint(5, int(size["height"]) - 5)

xoffset = rx - size["width"] / 2
yoffset = ry - size["height"] / 2

ActionChains(driver) \
    .move_to_element_with_offset(element, xoffset, yoffset) \
    .click() \
    .perform()

같은 위치를 터치 입력으로 누를 수도 있습니다.

The same point can be activated with touch input.

ActionChains(driver) \
    .touch_move_to_element_with_offset(element, xoffset, yoffset) \
    .touch_click() \
    .perform()

모바일 관련 기능 / Mobile Features

모바일 테스트를 위해 다음 기능을 제공합니다.

The following APIs support mobile-oriented testing.

  • element.touch_click()
  • element.click(input_type="touch")
  • ActionChains(driver).touch_click()
  • ActionChains(driver).double_tap(element)
  • ActionChains(driver).long_press(element)
  • ActionChains(driver).touch_drag_and_drop(source, target)
  • driver.touch_scroll_by(x, y)
  • driver.touch_scroll_to(x, y)
  • element.touch_scroll_into_view()
  • MobileEmulationExtension("android")
  • MobileEmulationExtension("ios")

모바일 에뮬레이션 확장은 UA, viewport, device scale factor, touch emulation, locale, timezone 등을 CDP Emulation.* 명령으로 적용합니다. 브라우저 attach, 페이지 이동, context 변경, 새 탭 감지 시점에 다시 적용됩니다.

The mobile emulation extension applies UA, viewport, device scale factor, touch emulation, locale, and timezone through CDP Emulation.* commands. Settings are reapplied after attach, navigation, context changes, and new-tab discovery.

from selenodriver import Chrome, MobileEmulationExtension

driver = Chrome(
    extensions=[
        MobileEmulationExtension("android")
    ]
)

직접 프로필 dict도 사용할 수 있습니다.

Custom profile dictionaries are also supported.

profile = {
    "device_name": "iPhone 16 Pro",
    "os_type": "ios",
    "width": 402,
    "height": 874,
    "devicePixelRatio": 3.0,
    "UA": "Mozilla/5.0 (iPhone; CPU iPhone OS 18_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1",
    "platform": "iPhone",
    "language": "ko-KR",
    "languages": ["ko-KR", "ko"],
}

driver = Chrome(extensions=[MobileEmulationExtension(profile)])

현재 구현 범위 / Implementation Status

This is an early compatibility layer, not a full Selenium replacement yet.

Implemented:

  • Chrome
  • By
  • WebElement
  • NoSuchElementException
  • WebDriverWait
  • ActionChains
  • Keys
  • Select
  • Options / ChromeOptions
  • MobileEmulationExtension
  • extension hooks for external/private modules
  • Selenium-like import paths under selenodriver.webdriver.*
  • common expected conditions
  • locators: CSS selector, XPath, id, name, tag name, class name
  • element actions/properties: click, mouse_click, touch_click, js_click, submit, scroll_into_view, shadow_root, send_keys, clear, text, tag_name, get_attribute, get_dom_attribute, get_property, value_of_css_property, is_selected, size, location, rect
  • browser helpers: get, back, forward, refresh, extension hooks, init scripts, auto_wait, implicitly_wait, set_script_timeout, timeouts, session_id, capabilities, window size/position, legacy find aliases, find_element, find_element_location, find_element_absolute_location, find_elements, execute_script, send_cdp, execute_cdp_cmd, scroll_to, scroll_by, touch_scroll_by, touch_scroll_to, page_source, title, current_url, current_window_handle, window_handles, switch_to.window, switch_to.frame, switch_to.active_element, cookies, save_screenshot, close, quit
  • action chains: click, touch_click, double_click, double_tap, context_click, move_to_element, move_to_element_with_offset, touch_move_to_element_with_offset, move_by_offset, drag_and_drop, drag_and_drop_by_offset, touch_drag_and_drop, touch_drag_by_offset, click_and_hold, long_press, release, send_keys, send_keys_to_element, key_down, key_up, pause
  • expected conditions: presence_of_element_located, visibility_of_element_located, element_to_be_clickable, invisibility_of_element_located, alert_is_present, title_is, title_contains, url_contains, url_to_be, url_matches, text checks, and window count checks

더 자세한 사용법은 한국어 가이드와 English guide에 정리되어 있습니다.

For complete usage details, see the Korean guide or the English guide.

License

This project is licensed under the GNU Affero General Public License v3.0.

이 프로젝트는 GNU Affero General Public License v3.0으로 배포됩니다.

selenodriver depends on nodriver, which is licensed under AGPL-3.0, so this project follows the same license family.

개발 / Development

PyPI에서 설치 / Install from PyPI:

python -m pip install selenodriver

로컬 개발 및 테스트 / Local development and tests:

python -m pip install -e .
python -m pip install pytest
pytest

실제 브라우저 smoke test / Real-browser smoke tests:

$env:SELENODRIVER_RUN_SMOKE='1'
pytest -m smoke

Metadata

Release files for selenodriver 0.1.1

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

Source distribution (sdist)

Source distribution for selenodriver 0.1.1
File Size Uploaded Provenance Actions
selenodriver-0.1.1.tar.gz 74.9 kB Without provenance Details for selenodriver-0.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for selenodriver 0.1.1
File Interpreter ABI Platform Actions
selenodriver-0.1.1-py3-none-any.whl Python 3 none any Details for selenodriver-0.1.1-py3-none-any.whl

Total release size: 134.5 kB

Release files / selenodriver-0.1.1.tar.gz

Download URL selenodriver-0.1.1.tar.gz
Size 74.9 kB
Tags Source
SHA-256 checksum
How to use checksums
18eedf2dfc59fdf1b39ee849caccafe3435c0b3dddbc48ad90ac02a2f2f194f0
BLAKE2b-256 checksum
How to use checksums
f4750e8d4cf9fab81aefe87203dde9819389a66071dd02f54868b0e9a13566aa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.1

Release files / selenodriver-0.1.1-py3-none-any.whl

Download URL selenodriver-0.1.1-py3-none-any.whl
Size 59.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7ed7fab1d7c7a2fc2b96ea9f8b639206522417ad6fe33fef427cc961f57295cf
BLAKE2b-256 checksum
How to use checksums
7b70c74c5e5fa40d637f4048d7a4c260e990d38d33b6d9bbf4b0f9ef459fabbb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.1

Security for selenodriver 0.1.1

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

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