NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #2144 most downloaded on PyPI
Parsel is a library to extract data from HTML and XML using XPath and CSS selectors
Last release 6 days ago
28 Sep 2026
Release timing varies
gaps range from 3 weeks to 2.5 years
Nearly every release is documented
notes for 27 of 28 stable releases
Nothing withdrawn
no release was ever pulled
11 years old
28 releases · first in 2015
Bump version: 1.12.0 → 1.12.1
Bump version: 1.12.0 → 1.12.1
xpath() and css() call when
using lxml 5.4.0 or later.Bump version: 1.11.0 → 1.12.0
Bump version: 1.11.0 → 1.12.0
type is not specified, Selector now detects input as JSON only
if it is a JSON object or array. Other valid JSON, such as 123 or
"foo", is now handled as HTML. Pass type="json" to get the old
behavior.type is now respected when the input or root is valid
JSON. Before, type was ignored and the input was handled as JSON. As a
result, selectors for text nodes and attribute values whose content is
valid JSON, e.g. "1", now keep the type of their parent selector
instead of "json".type is not specified, body is now detected as JSON for any
spelling of the UTF-8 encoding name, e.g. "UTF-8" or "utf8".type is not specified, Selector now handles input that starts
with an XML declaration (<?xml ...?>) as XML instead of HTML. Pass
type="html" to get the old behavior.body handling for UTF-16 and other encodings that are not UTF-8:
multi-byte characters are no longer garbled, and bytes that the encoding
cannot decode are now replaced with U+FFFD instead of truncating the
document.Selector raising XMLSyntaxError for an XML body that is
empty after stripping whitespace and null bytes. It now gets the same empty
root as the equivalent text.xpath() are now always used as XPath
variables. Before, extensions and regexp were passed to lxml as
evaluation options. To use custom XPath functions, register them with
parsel.xpathfuncs.set_xpathfunc() instead.xpath(".") now works on selectors for text nodes and attribute values,
returning the selector itself instead of an empty list.jmespath() now works on selectors of type "text" and on selectors
for text nodes and attribute values.::attr() pseudo-element producing an invalid XPath
expression for attribute names that are not valid XPath names, e.g.
::attr(foo\:bar).drop() on an XML selector also removing the tail text of the
dropped element.drop() raising ValueError instead of
CannotDropElementWithoutParent for the root element of an XML selector.lxml_version, lxml_huge_tree_version and
LXML_SUPPORTS_HUGE_TREE constants from parsel.selector. All
supported lxml versions support huge_tree.packaging.parsel.utils.iflatten() is now lazy for nested iterables as well.iterlinks(), and how
to get the XPath expression of a selector.parsel-cli from the documentation.One column per quarter.
Removed Selector.remove() and SelectorList.remove() , deprecated in 1.7.0.
Removed support for Python 3.9 and PyPy 3.10.
Added support for Python 3.14 and PyPy 3.11.
The following dependencies now have a minimum supported version:
lxml >= 5.1.0packaging >= 23.0jmespath >= 1.0.0Removed Selector.remove() and SelectorList.remove(), deprecated in 1.7.0.
The Selector() constructor now accepts bytearray values for the body argument in addition to bytes.
attrib and remove_namespaces() no longer fail with unhandled exceptions on JSON selectors.
Switched the build system to hatchling.
CI fixes and improvements.
Removed support for Python 3.8.
"utf8" to "utf-8" everywhere. The former name is not supported in certain environments.Removed the dependency on pytest-runner .
pytest-runner.Makefile.Now requires cssselect >= 1.2.0 (this minimum version was required since 1.8.0 but that wasn't properly recorded)
cssselect >= 1.2.0 (this minimum version was required since 1.8.0 but that wasn't properly recorded)__str__ or __repr__ on some JSON selectorsblackRemove a Sphinx reference from NEWS to fix the PyPI description
twine check CI check to detect such problemsThe Selector.remove() and SelectorList.remove() methods are deprecated and replaced with the new Selector.drop() and SelectorList.drop() methods which…
Python 3.4 is no longer supported
Selector.remove() and SelectorList.remove() methods to remove selected elements from the parsed document treeThe NEWS file is included as part of the long description of the package, and the Python Package Index does not allow Sphinx text roles.
The NEWS file is included as part of the long description of the
package, and the Python Package Index does not allow Sphinx text
roles.
Selector.remove_namespaces received a significant performance improvementdata within the printable representation of a selector
(repr(selector)) now ends in ... when truncated, to make the
truncation obvious.Bump version: 1.5.0 → 1.5.1
Bump version: 1.5.0 → 1.5.1
has-class XPath function handles newlines and other separators
in class names properly;…now call Selector.get internally. It can be backwards incompatible in case of custom Selector subclasses which override Selector.extract without doing…
Selector.attrib and SelectorList.attrib properties which make
it easier to get attributes of HTML elements.css2xpath), so there is
less overhead when the same CSS expression is used several times..get() and .getall() selector methods are documented and recommended
over .extract_first() and .extract().One more change is that .extract() and .extract_first() methods
are now implemented using .get() and .getall(), not the other
way around, and instead of calling Selector.extract all other methods
now call Selector.get internally. It can be backwards incompatible
in case of custom Selector subclasses which override Selector.extract
without doing the same for Selector.get. If you have such Selector
subclass, make sure get method is also overridden. For example, this::
class MySelector(parsel.Selector):
def extract(self):
return super().extract() + " foo"
should be changed to this::
class MySelector(parsel.Selector):
def get(self):
return super().get() + " foo"
extract = get
Selector and SelectorList can't be pickled because pickling/unpickling doesn't work for lxml.html.HtmlElement; parsel now raises TypeError explicitly
Selector and SelectorList can't be pickled because
pickling/unpickling doesn't work for lxml.html.HtmlElement;
parsel now raises TypeError explicitly instead of allowing pickle to
silently produce wrong output. This is technically backwards-incompatible
if you're using Python < 3.6.* Fix artifact uploads to pypi.
Add SelectorList.get and SelectorList.getall methods as aliases for SelectorList.extract_first and SelectorList.extract respectively
Add SelectorList.get and SelectorList.getall
methods as aliases for SelectorList.extract_first
and SelectorList.extract respectively
Add default value parameter to SelectorList.re_first method
Add Selector.re_first method
Add replace_entities argument on .re() and .re_first()
to turn off replacing of character entity references
Bug fix: detect None result from lxml parsing and fallback with an empty document
Rearrange XML/HTML examples in the selectors usage docs
Travis CI:
Change default HTML parser to lxml.html.HTMLParser _, which makes easier to use some HTML specific features
lxml.html.HTMLParser <https://lxml.de/api/lxml.html.HTMLParser-class.html>_,
which makes easier to use some HTML specific featuresIntegrate py.test runs with setuptools (needed for Debian packaging)
NEWSFix bug in exception handling causing original traceback to be lost
Added docstrings for csstranslator module and other doc fixes
* Documentation fixes
* Updated documentation * Extended test coverage
Support for extending SelectorList
Try workaround for travis-ci/dpl#253
* Add base_url argument
Rename module unified -> selector and promoted root attribute
Setup Sphinx build and docs structure
* First release on PyPI.
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →