scrapy/scrapy · error · ValueError
{self.__class__.__name__}.__init__() received both response
Error message
{self.__class__.__name__}.__init__() received both response and text What it means
Selector (scrapy.selector.Selector, the unified wrapper over parsel) raises ValueError in __init__ when both response and text are passed. A selector is constructed from exactly one source: a Response object (using its body/encoding) or a raw text string. Supplying both is ambiguous, so it is rejected immediately.
Source
Thrown at scrapy/selector/unified.py:71
.. note:: JSON selector support requires ``parsel`` 1.8.0 or higher. With
older versions setting ``type`` to ``"json"`` or ``"text"`` is not
supported.
"""
__slots__ = ["response"]
selectorlist_cls = SelectorList
def __init__(
self,
response: TextResponse | None = None,
text: str | None = None,
type: SelectorType | None = None, # noqa: A002
root: Any | None = _NOT_SET,
**kwargs: Any,
):
if response is not None and text is not None:
raise ValueError(
f"{self.__class__.__name__}.__init__() received both response and text"
)
# A response that is neither HTML nor XML, e.g. a JSON one, keeps type
# unset, so that parsel determines it from the body.
if type is None:
if isinstance(response, XmlResponse):
type = "xml" # noqa: A001
elif response is None or isinstance(response, HtmlResponse):
type = "html" # noqa: A001
if text is not None:
response = _response_from_text(text, type)
if response is not None:
text = response.text
kwargs.setdefault("base_url", get_base_url(response))
View on GitHub (pinned to 06af687662)
Solutions
- Pass only one source: Selector(response=resp) or Selector(text=html_string).
- In wrapper functions, branch on which argument is provided before constructing.
- For raw bytes from a response, use response.text or let the response construct the selector itself (response.selector).
Example fix
# before sel = Selector(response=response, text=response.text) # ValueError # after sel = Selector(response=response)
Defensive patterns
Strategy: validation
Validate before calling
assert not (response is not None and text is not None), \
'Selector accepts either response or text, not both' Try / catch
try:
sel = Selector(response=response, text=text)
except ValueError:
sel = Selector(response=response) if response is not None else Selector(text=text) Prevention
- Pass exactly one of response or text.
- In wrapper functions, branch on which argument is provided instead of forwarding both.
- Prefer response.selector when you already hold the response.
When it happens
Trigger: Selector(response=resp, text='<html>...') or Selector(resp, text=html_string); helper functions that default both parameters and forward them unconditionally; copy-pasting shell examples into code with both kwargs filled.
Common situations: Wrapping selectors in utility functions where response and text both have defaults; feeding an encoded body string alongside the response for 'safety'; interactive scrapy shell habits carried into production code.
Related errors
- Link urls must be str objects, got {got}
- Object {obj!r} must be {expected_types_str}, not {type(obj).
- Invalid entry point {entry_point.name}
- Incorrect type: expected Response or Request, got {type(resu
- Incorrect type: expected Response or Failure, got {type(resu
AI-assisted analysis of scrapy/scrapy@06af687662 (2026-08-15).
Data as JSON: /api/errors/00fb92c2b21000cc.
Report an issue: GitHub.