D4Vinci/Scrapling · error · TypeError

You have to pass something to search with, like tag name(s),

Error message

You have to pass something to search with, like tag name(s), tag attributes, or both.

What it means

find_all() requires at least one filter argument. Unlike BeautifulSoup's find_all(), calling it completely empty is treated as a programmer error and raises TypeError instead of silently returning every element in the tree.

Source

Thrown at scrapling/parser.py:711

        ) as e:
            raise SelectorSyntaxError(f"Invalid XPath selector: {selector}") from e

    def find_all(
        self,
        *args: str | Iterable[str] | Pattern | Callable | Dict[str, str],
        **kwargs: str,
    ) -> "Selectors":
        """Find elements by filters of your creations for ease.

        :param args: Tag name(s), iterable of tag names, regex patterns, function, or a dictionary of elements' attributes. Leave empty for selecting all.
        :param kwargs: The attributes you want to filter elements based on it.
        :return: The `Selectors` object of the elements or empty list
        """
        if self._is_text_node(self._root):
            return Selectors()

        if not args and not kwargs:
            raise TypeError("You have to pass something to search with, like tag name(s), tag attributes, or both.")

        attributes: Dict[str, Any] = dict()
        tags: Set[str] = set()
        patterns: Set[Pattern] = set()
        results, functions, selectors = Selectors(), [], []

        # Brace yourself for a wonderful journey!
        for arg in args:
            if isinstance(arg, str):
                tags.add(arg)

            elif type(arg) in (list, tuple, set):
                arg = cast(Iterable, arg)  # Type narrowing for type checkers like pyright
                if not all(map(lambda x: isinstance(x, str), arg)):
                    raise TypeError("Nested Iterables are not accepted, only iterables of tag names are accepted")
                tags.update(set(arg))

            elif isinstance(arg, dict):

View on GitHub (pinned to 5d213a2d47)

Solutions

  1. Pass an explicit catch-all: find_all('*') selects all elements.
  2. If the args are built dynamically, default them: find_all(*(tags or ['*'])).
  3. Reconsider whether you actually wanted all elements — iterating children directly (page.children) is usually clearer.

Example fix

# before
selector.find_all()  # TypeError

# after
selector.find_all('*')
Defensive patterns

Strategy: validation

Validate before calling

filters = [f for f in built_filters if f]
results = selector.find_all(*(filters or ['*']))  # never call with zero args

Try / catch

try:
    results = selector.find_all(*args)
except TypeError as e:
    if 'pass something to search with' in str(e):
        results = selector.find_all('*')
    else:
        raise

Prevention

When it happens

Trigger: Calling selector.find_all() with no positional args and no kwargs — e.g. a wrapper function forwards an empty filter set: selector.find_all(*filters) where filters == [].

Common situations: Translating BeautifulSoup code that used find_all() to grab everything; generic helper functions that build filter lists dynamically and occasionally end up empty.

Related errors


AI-assisted analysis of D4Vinci/Scrapling@5d213a2d47 (2026-08-14). Data as JSON: /api/errors/48ce148d0584a44f. Report an issue: GitHub.