SeleniumHQ/selenium · error · TypeError

Expected object of type ScrollOrigin, got: {type(scroll_orig

Error message

Expected object of type ScrollOrigin, got: {type(scroll_origin)}

What it means

`ActionChains.scroll_from_origin` requires a `ScrollOrigin` object (built via `ScrollOrigin.from_element(...)` or `ScrollOrigin.from_viewport(...)`). Passing anything else (a WebElement, a string, a tuple) raises `TypeError`. ScrollOrigin bundles the origin plus x/y offsets and is the only acceptable argument shape.

Source

Thrown at py/selenium/webdriver/common/action_chains.py:362

    def scroll_from_origin(self, scroll_origin: ScrollOrigin, delta_x: int, delta_y: int) -> ActionChains:
        """Scroll by a provided amount based on a scroll origin (element or viewport).

        The scroll origin is either the center of an element or the upper left of the
        viewport plus any offsets. If the origin is an element, and the element
        is not in the viewport, the bottom of the element will first be
        scrolled to the bottom of the viewport.

        Args:
            scroll_origin: Where scroll originates (viewport or element center) plus provided offsets.
            delta_x: Distance along X axis to scroll using the wheel. A negative value scrolls left.
            delta_y: Distance along Y axis to scroll using the wheel. A negative value scrolls up.

        Raises:
            MoveTargetOutOfBoundsException: If the origin with offset is outside the viewport.
        """
        if not isinstance(scroll_origin, ScrollOrigin):
            raise TypeError(f"Expected object of type ScrollOrigin, got: {type(scroll_origin)}")

        self.w3c_actions.wheel_action.scroll(
            origin=scroll_origin.origin,
            x=scroll_origin.x_offset,
            y=scroll_origin.y_offset,
            delta_x=delta_x,
            delta_y=delta_y,
        )
        return self

    # Context manager so ActionChains can be used in a 'with .. as' statements.

    def __enter__(self) -> ActionChains:
        return self  # Return created instance of self.

    def __exit__(self, _type, _value, _traceback) -> None:
        pass  # Do nothing, does not require additional cleanup.

View on GitHub (pinned to aa36b38e69)

Solutions

  1. Wrap an element origin: `from selenium.webdriver.common.actions.wheel_input import ScrollOrigin; ActionChains(driver).scroll_from_origin(ScrollOrigin.from_element(el, 0, 0), 0, 100).perform()`.
  2. Wrap a viewport origin: `ScrollOrigin.from_viewport(x_offset, y_offset)`.
  3. If you just want to scroll to an element, use `scroll_to_element(element)` instead.
  4. If you want pure delta scroll, use `scroll_by_amount(delta_x, delta_y)`.

Example fix

// before
ActionChains(driver).scroll_from_origin(element, 0, 100).perform()  # TypeError
// after
from selenium.webdriver.common.actions.wheel_input import ScrollOrigin
ActionChains(driver).scroll_from_origin(ScrollOrigin.from_element(element), 0, 100).perform()
Defensive patterns

Strategy: type-guard

Validate before calling

from selenium.webdriver.common.actions.wheel_input import ScrollOrigin
origin = ScrollOrigin.from_element(element, 0, 0)
assert isinstance(origin, ScrollOrigin), "scroll_from_origin needs a ScrollOrigin"
ActionChains(driver).scroll_from_origin(origin, 0, 100).perform()

Type guard

from selenium.webdriver.common.actions.wheel_input import ScrollOrigin
def is_scroll_origin(value) -> bool:
    return isinstance(value, ScrollOrigin)

Try / catch

try:
    ActionChains(driver).scroll_from_origin(origin, dx, dy).perform()
except TypeError:
    from selenium.webdriver.common.actions.wheel_input import ScrollOrigin
    if hasattr(origin, "id"):
        origin = ScrollOrigin.from_element(origin)
    else:
        origin = ScrollOrigin.from_viewport()
    ActionChains(driver).scroll_from_origin(origin, dx, dy).perform()

Prevention

When it happens

Trigger: `ActionChains(driver).scroll_from_origin(element, 0, 100)` (passing a WebElement directly), `scroll_from_origin("viewport", 0, 100)` (a string), or `scroll_from_origin((0,0), 0, 100)` (a tuple). The developer forgot to wrap the origin in a ScrollOrigin.

Common situations: Mixing up `scroll_from_origin` with `scroll_to_element`/`scroll_by_amount`. Porting code from another library. Reading an outdated tutorial that passed a bare element.

Related errors


AI-assisted analysis of SeleniumHQ/selenium@aa36b38e69 (2026-08-14). Data as JSON: /api/errors/5096aa518c05a462. Report an issue: GitHub.