NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #2229 most downloaded on PyPI
A simple Python module for parsing human names into their individual components.
Last release 22 days ago
12 Sep 2026
Ships unpredictably
gaps range from 8 days to 2.7 years
Most releases are documented
notes for 43 of 60 stable releases
Nothing withdrawn
no release was ever pulled
15 years old
62 releases · first in 2012
Parsing fixes and new honorific vocabulary; nothing in the API is removed or renamed.
Parsing fixes and new honorific vocabulary; nothing in the API is removed or renamed.
The fixes cluster around post-nominals and titles. A space-separated run of post-nominals keeps the spacing the writer typed (John Smith MD PhD → suffix MD PhD, not MD, PhD), and the acronyms that are also surnames — Rai, Cha, Ba — no longer take a name's family name. A run of titles addresses by its last, and a trailing abbreviated title reads as a title. CJK names and honorifics written with a full stop of any width now parse. The additions are renunciate and royal given-name titles, Devanagari and the first Bengali honorifics, and two AmbiguityKind members that report a reading nothing in the name decided.
Incompatibility: a Lexicon pickled by 2.1.x or 2.2.x with a caller-added entry written with a fullwidth or ideographic full stop, or in NFD, no longer loads (ValueError: incompatible Lexicon pickle: entries are not normalized). The shipped vocabulary is unaffected; rebuild the Lexicon from its source rather than unpickling it.
Full release notes: https://nameparser.readthedocs.io/en/latest/release_log.html
One column per quarter.
Every 1.x name still imports with a DeprecationWarning until 3.0. The rename itself changes no parse.
A rename plus about thirty parsing fixes.
The nameparser.config word lists are renamed to match the Lexicon they feed — PREFIXES → PARTICLES, BOUND_FIRST_NAMES → BOUND_GIVEN_NAMES, FIRST_NAME_TITLES → GIVEN_NAME_TITLES, SUFFIX_NOT_ACRONYMS → SUFFIX_WORDS, and NON_FIRST_NAME_PREFIXES → NON_GIVEN_NAME_PARTICLES — and are now frozen. Every 1.x name still imports with a DeprecationWarning until 3.0. The rename itself changes no parse.
The fixes cluster around surname particles, largely what a declared name_order means for Latin-script names; then maiden-name clauses, Arabic bound given names, and credentials after a comma.
Breaking: TITLES.add("dean") now raises AttributeError. Build a private Constants (c = Constants(); c.titles.add("dean"); HumanName(name, constants=c)) or a Lexicon (Parser(lexicon=Lexicon.default().add(titles={"dean"}))) instead. See the migration guide.
Full release notes: https://nameparser.readthedocs.io/en/latest/release_log.html
nameparser 2.1 makes East Asian names work without configuration. Chinese, Japanese and Korean names written in their own scripts are read family-firs
nameparser 2.1 makes East Asian names work without configuration. Chinese, Japanese and Korean names written in their own scripts are read family-first, unspaced Korean names are split against the census surname list, and CJK honorifics are recognized whether they are spaced or written against the name.
The two conventions that need you to declare a language, Han segmentation and kana-aware division, ship as the opt-in locales.ZH and locales.JA packs.
Most of this is default-on, deliberately: wherever nameparser acts unasked, the script itself settles the convention and no language detection is involved. Only names bearing CJK characters parse differently from 2.0 — measured across 751 corpus names, with zero changes on Latin-only input.
Existing HumanName code keeps working through 2.x.
Please open an issue for anything that parses wrong.
What 2.0 removes is the batch of deprecations announced in 1.3 and 1.4; if your suite runs clean on 1.4 under python -W error::DeprecationWarning , yo…
nameparser 2.0 — a new immutable core API, with full compatibility for existing code through 2.x.
parse() returns an immutable ParsedName whose seven fields are named for what they are (given, family) rather than where they sit in a Western name, configured by two frozen value objects — a Lexicon of vocabulary and a Policy of behavior — instead of a mutable global. Every parse can tell you what it had to guess at (ambiguities) and exactly where each token came from (tokens, with character spans).
HumanName keeps working. It is now a compatibility facade over the same pipeline and stays through 2.x — most 1.x code needs no changes. What 2.0 removes is the batch of deprecations announced in 1.3 and 1.4; if your suite runs clean on 1.4 under python -W error::DeprecationWarning, you are nearly done. One removal changes results silently rather than raising: name == "John Smith" is now False — use matches(). The migration guide has the field-by-field map.
Highlights:
title, given, middle, family, suffix, nickname, maiden — plus derived views (family_particles, given_names, …), render(spec), initials(), capitalized(), and semantic comparison via matches()/comparison_key()Lexicon + Policy, partial PolicyPatch deltas, Policy.patched(), and Parser.revise() for tag-preserving correctionsPolicy(name_order=FAMILY_FIRST)) and opt-in locale packs (parser_for(locales.RU)) — never auto-detectednée, geb., …)The full change list is in the release log; rc1/rc2 testers can read its "Changed since 2.0.0rc1" section. Please report anything the migration missed on #284.
🤖 Generated with Claude Code
Second release candidate for nameparser 2.0.0. Install it with pip install --pre nameparser (a plain pip install will not select a pre-release). Pleas
Second release candidate for nameparser 2.0.0. Install it with pip install --pre nameparser (a plain pip install will not select a pre-release). Please report anything the migration missed on #284.
rc2 is rc1 plus the post-rc1 API-polish bundle (#290). If you tested rc1, the release log's "Changed since 2.0.0rc1" section lists exactly what you'd notice:
Role became a StrEnum — members compare and stringify as their field namesParsedName.tokens_for() raises ValueError for unknown roles instead of silently returning no tokens, and accepts role-name stringsParsedName.as_dict()'s include_empty is keyword-onlyHumanName subscripting accepts Role memberschargé d'affaires split into chainable words, both spellings; seven credential acronyms removed), and storing a new multi-word entry now warns — a restored pre-2.0 Constants pickle carrying all eight is cleaned up silentlyPolicyPatch's repr shows only the fields a patch setsSTABLE_TAGS, Policy.patched(), Parser.matches(), Parser.capitalized(), and Parser.revise()🤖 Generated with Claude Code
Breaking changes — read before upgrading
This is a release candidate. A plain
pip install nameparserwill not pick it up — pre-releases are opt-in:pip install --pre nameparser==2.0.0rc1Please try it against your real code and report anything the migration missed on #284. The final 2.0.0 follows once the RC settles.
nameparser 2.0 adds a new parsing API alongside HumanName. HumanName keeps working unchanged as a compatibility facade over the same pipeline, and stays through the 2.x series — if your code runs warning-free on 1.4.0, most of 2.0 will not affect you.
parse(text) returns an immutable ParsedName whose seven fields are named for what they are — given, family — rather than where they sit in a Western name:
from nameparser import parse
name = parse("Dr. Juan Q. Xavier de la Vega III")
name.given # 'Juan'
name.family # 'de la Vega'
name.family_base # 'Vega' (particles split off)
name.suffix # 'III'Lexicon of vocabulary and a Policy of behavior replace the mutable global Constants. Both are immutable, hashable value objects; parsing is a pure function of the text, a lexicon, and a policy — nothing global is read or mutated. Build a reusable Parser(lexicon=..., policy=...).Policy(name_order=FAMILY_FIRST) and FAMILY_FIRST_GIVEN_LAST (#270).parser_for(locales.RU) folds in East Slavic patronymic order; locales.TR_AZ covers Turkic markers. Packs are pure data, they compose, and they're never auto-detected.née, geb. → a maiden field, #274), typographic nickname delimiters (smart quotes, guillemets, CJK brackets, #273), and non-Latin vocabulary — Cyrillic, Greek, Arabic, Hebrew titles and particles (#269).ParsedName.ambiguities instead of guessing silently — e.g. "John Smith MA" reports that MA was read as a credential rather than a surname. A reading the vocabulary settles on its own reports nothing.Tokens carrying (start, end) offsets into the original string, reachable via tokens_for(Role.GIVEN) — so you can highlight or re-slice the input a parse came from.The removals are the deprecations announced in 1.3.0 and 1.4.0 coming due. The one that matters most:
HumanName.__eq__ and __hash__ are removed (#223). Instances now compare and hash by identity, so HumanName("John Smith") == "John Smith" is now False where 1.x returned True. This changes results silently rather than raising — it's the one removal that can slip into production unnoticed. Use matches() to compare names and comparison_key() as a dict/sort key.Also: minimum Python is now 3.11 (#257); bytes input is gone (decode first, #245); regex configuration, subclass parsing hooks, HumanName slicing, and empty_attribute_default are removed. Each raises with a migration hint (except the __eq__ case above).
HumanName is unchanged, so most users need to do nothing yet. If you customized Constants, subclassed HumanName, or compared names with ==, see the migration guide for the field-by-field and attribute-by-attribute map.
Deprecate passing constants=None to HumanName (or assigning hn.C = None ): it silently builds a fresh Constants() , discarding any customizations the…
Constants.copy(), a detached deep copy that preserves the source instance's current customizations (unlike Constants(), which always starts from library defaults) -- useful as CONSTANTS.copy() for a private snapshot of the shared config (#260)constants=None to HumanName (or assigning hn.C = None): it silently builds a fresh Constants(), discarding any customizations the caller may have expected to carry over from the shared CONSTANTS. Emits DeprecationWarning; will raise TypeError in 2.0. Use constants=Constants() for fresh library defaults or constants=CONSTANTS.copy() for a private snapshot instead (closes #260)Constants.empty_attribute_default for removal in 2.0 (#255): once None support goes, the only legal value left is the default '', so a dial with one position isn't configuration. Emits DeprecationWarning; reading the attribute is unaffectedTupleManager/RegexTupleManager (CONSTANTS.regexes.typo, CONSTANTS.capitalization_exceptions.typo, etc.) for removal in 2.0 (#256): a misspelled or omitted key currently degrades silently (None/EMPTY_REGEX) with no traceback pointing at the typo. Emits DeprecationWarning naming the miss and the known keys; will raise AttributeError in 2.0. .get() remains available for intentional soft accessHumanName slice access (name[1:-3]) and item assignment (name['first'] = value) for removal in 2.0 (#258): field access by position has no real use case, and item assignment duplicates plain attribute assignment. Both emit DeprecationWarning; string-key access (name['first']) is unaffectedSetManager.add_with_encoding() itself for removal in 2.0 (#245), regardless of argument type: use add() instead (decoding bytes first). Previously only the bytes path warned; the str path was silent even though the whole method goes awayConstants pickle (written by nameparser <= 1.2.x, before the 1.3.0 pickle fix) for removal in 2.0 (#279): __setstate__'s migration shim currently skips the stale computed-property key silently. Emits DeprecationWarning once per call telling users to re-pickle; will raise ValueError in 2.0"Lastname, Firstname" comma format not being recognized when the input uses the Arabic comma ، (U+060C, the standard comma in Arabic/Persian/Urdu text) or the fullwidth CJK comma , (U+FF0C) instead of the ASCII comma: both variants now also split the format and no longer leak into the parsed output (closes #265)Full changelog: https://github.com/derek73/python-nameparser/blob/master/docs/release_log.rst
Patch release with two output-corruption bug fixes. No API changes. Full details in the release log .
Patch release with two output-corruption bug fixes. No API changes. Full details in the release log.
first/last/etc., so a copy-pasted right-to-left name silently failed equality and dedup. Disable via CONSTANTS.regexes.bidi = False.str() no longer corrupts name text containing the substring "None" when empty_attribute_default is None (#254) — e.g. "Nonez Smith" rendered as "z Smith". Empty attributes are now substituted as '' before the format string is applied, instead of scrubbing the interpolated "None" from the output afterward. Present since 2016; the default '' configuration was never affected.This release is the bridge release ahead of 2.0: every planned 2.0 removal now has its replacement shipped and emits a DeprecationWarning naming it, s…
This release works through essentially the entire backlog of open issues — nearly every bug and feature request in the tracker, including several dating back to 2014. Alongside the fixes, it adds long-requested functionality: maiden name support, surname-prefix splitting, patronymic name ordering, and a set of new customization hooks on Constants.
The release was developed with Claude Code, and every fix and feature ships with regression tests. The complete list of changes is below.
This release is the bridge release ahead of 2.0: every planned 2.0 removal now has its replacement shipped and emits a DeprecationWarning naming it, so code can migrate while both APIs work. Full details in the release log.
== and hash() on HumanName (#223) — the design's three promises (case-insensitive equality, equality with plain strings, hashability) are mutually inconsistent, equality depends on string_format, and maiden is invisible to it. Replacements, new in this release: matches() for semantic comparison (name.matches("Smith, John") and name.matches("John Smith") both match) and comparison_key() for sets, dicts, dedup, and sorting.bytes input (#245) — decode first, e.g. value.decode('utf-8'); the encoding kwarg is deprecated with it.SetManager.__call__ (#243) — iterate the manager or copy with set(manager).SetManager.remove() of a missing member (#243) — will raise KeyError in 2.0 like set.remove; new discard() is the intentional ignore-missing spelling.HumanName is no longer its own iterator; iter(name) returns a fresh independent iterator (fixes state corruption from break/nested loops/len() mid-loop) (#225)unparsable attribute removed (unreachable since 2013; use len(name) == 0); __ne__ removed (derived from __eq__)REGEXES and CAPITALIZATION_EXCEPTIONS are now dicts — iterate with .items() (#227, #233)__process_initial__ renamed _process_initial (dunder names are reserved)abdul, abu, …) join forward into the first name (#150); disable via CONSTANTS.bound_first_names.clear()"Major.") parses as a title (#109)CONSTANTS it reads — parse results no longer depend on what was parsed earlier in the process, and parsing is thread-safe against config writesmaiden field with maiden_delimiters routing (#22); given_names (#157); last_base/last_prefixes for surname particles (#130, #132)patronymic_name_order for Russian and Turkic formal-order names (#85, #185); middle_name_as_last (#133); non_first_name_prefixes (#121); expanded international titles and prefixes (#18, #101, #187)initials_separator (#171), suffix_delimiter (#156), nickname_delimiters (#110, #112), suffix_acronyms_ambiguous (#111)TupleManager rejects malformed input (#242), membership checks normalize like every other operation (#244), Constants subclasses are respected (#226)Constants survive pickle/deepcopy (#167, #168, #169); many parsing fixes — suffix boundaries with prefixed last names (#100), repeated prefix chains (#208), degenerate comma input, roman-numeral and suffix recognition in comma formats (#136, #144), and moreFix initials() interpolating the literal None for empty name parts when empty_attribute_default = None (e.g. "J. None D." ); empty parts now render as
initials() interpolating the literal None for empty name parts when empty_attribute_default = None (e.g. "J. None D."); empty parts now render as an empty string and a fully-empty result returns empty_attribute_defaultpython -m nameparser "Name String" command-line helper that prints a parsed nametests.py into a tests/ pytest packageFull Changelog: v1.2.0...v1.2.1
Drop Python 2 and Python < 3.10 support; Python 3.10–3.14 now required
py.typed marker)pyproject.toml, drop setup.pyENCODING constant, next() aliases)Fix case when we have two same prefixes in the name
Fix bug in is_suffix() handling of lists
is_suffix() handling of lists (#129)Nothing published for this version
Add more titles, suffixes and and prefixes (#120, #127, #128, #119, #116, #114, #117, #126, #102, #123)
Fix Python 3.8 syntax error warning
Fix deprecation warning on Python 3.7
Better nickname handling of multiple single quotes
fix sys.stdin usage when stdin doesn't exist
Nothing published for this version
Fix overzealous regex for "Ph. D."
surnames attribute as aggregate of middle and last namesNothing published for this version
Nothing published for this version
Fix handling of "do" and "dos" Portuguese prefixes (#71, #72)
Fix python version check
Fix python version check (#64)
Nothing published for this version
Add the full set of Italian derivatives from "di"
Remove emojis from initial string by default with option to include emojis
Added names scrapped from VIAF data, thanks daryanypl
Fix error for names that end with conjunction
Fix error for names that end with conjunction (#54)
Refactor join_on_conjunctions(), fix #53
Refactor join_on_conjunctions(), fix #53
Remove "bishop" from titles because it also could be a first name
Remove "CONSTANTS.suffixes", replaced by "suffix_acronyms" and "suffix_not_acronyms"
Skip pickle tests if pickle not installed
Fix string format when empty_attribute_default = None
empty_attribute_default = None (#45)Add CONSTANTS.empty_attribute_default to customize value returned for empty attributes
CONSTANTS.empty_attribute_default to customize value returned for empty attributes (#44)Improve customization documentation
Fix first name clash with suffixes
Fix #39, capitalization bug with initials that are also conjunctions ("e" and "y")
fix bytestring handling on python 2.x
Separate suffixes that are acronyms to handle periods differently, fixes #29, #21
Fixes for #36, better handling of roman numerals at the end of a name
Make HumanName instances pickleable
Fix strings that start with conjunctions
Fix handling of string encoding in python 2.x
Fix #24, handle first name also a prefix
Handle trailing suffix in last name comma format (#3). Removes support for titles with periods but no spaces in them, e.g. "Lt.Gen.".
Retain original string in "original" attribute.
Fix PyPi package missing config module.
Fix PyPi package missing config module.
Initial refactoring of the constants and configurations system to make it easier to modify (#1). You can now adjust the parser's configuration like so
Initial refactoring of the constants and configurations system to make it easier to modify (#1). You can now adjust the parser's configuration like so:
>>> from nameparser import HumanName
>>> from nameparser.config import CONSTANTS
>>> CONSTANTS.titles.add('dean', 'Chemistry')
>>> hn = HumanName("Assoc Dean of Chemistry Robert Johns")
>>> hn
<HumanName : [
Title: 'Assoc Dean of Chemistry'
First: 'Robert'
Middle: ''
Last: 'Johns'
Suffix: ''
Nickname: ''
]>
New instructions for customizing the parser are included in the new documentation.
Install:
pip install nameparser
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →