The Taken Package-Name Playbook: Owner Trace to Transfer or Rename
Show whether a taken PyPI, npm, crates.io, or Hex name is squatted, abandoned, or live, reach its owner, file with dated evidence, and know when to rename.
Key takeaways
- PyPI, npm, and Hex can transfer a taken name without the owner's consent if their criteria are met, but crates.io will not transfer a crate without the current owner's explicit approval and declines all mediation requests.
- Under PEP 541, a PyPI project counts as abandoned only when all three conditions hold: the owner is unreachable, there have been no releases in twelve months, and the owner shows no activity on the project's home page.
- npm asks you to copy support@npmjs.com on your message to the owner and wait at least 4 weeks, and Hex grants the name after 30 days of owner silence if the Hex team agrees.
- In one documented PyPI case, a PEP 541 request took about 4.5 months just to reach its first reachability step, while the open queue grew from 261 to 331 issues, so a launch should never wait on the queue.
- In Refolk's index of professional profiles, only 45 US profiles carry a Maintainer title with the Python skill and only 3 with Rust, so owner traces have to start from commit metadata and employer records, not job titles.
- Deleting a package frees its name for anyone, and JFrog found pingdomv3 re-registered the same day its owner removed it, so ask for a transfer rather than a deletion.
This playbook is for engineering managers, technical founders, developer-relations leads, and sourcers who need a registry name that a dead-looking package already holds on PyPI, npm, crates.io, or Hex. It covers five things in order. First, write down whether the package is squatted, abandoned, or live under that registry's own rules. Second, trace an owner whose listed email bounces. Third, run a dated contact sequence that leaves the evidence the registry asks for. Fourth, file. Fifth, at a set checkpoint, decide whether to keep waiting or ship under a scoped or new name.
Which registries will transfer a taken name without the owner's consent?
PyPI, npm, and Hex can transfer a taken name without the owner's consent when their criteria are met. crates.io will not, and RubyGems does not in practice. Settle this before you write to anyone, because it decides whether you are starting a dispute or a rename.
| Registry | Transfer without consent | Candidate wait | Who contacts |
|---|---|---|---|
| PyPI | Yes, if PEP 541 criteria are met | None stated; staff check up to 6 weeks | Candidate, then PyPI staff |
| npm | Yes, at support's discretion | 4 weeks, support in CC | Candidate |
| Hex | Yes, if the team agrees | 30 days, support in CC | Candidate |
| crates.io | No | Not applicable | Candidate only; mediation declined |
| RubyGems | No in practice (staff replies) | Not published | Candidate |
What each policy actually says:
- PyPI (PEP 541). A project is abandoned only when all three conditions hold: the owner is not reachable, there have been no releases in the past twelve months, and the owner shows no activity on the project's home page. Separately, a project is invalid and gets removed if it is name squatting, meaning it has no functionality or is empty. PEP 541 is PyPI's name-retention policy.
- npm. A package name is squatted if the package has no genuine function. You email the owner with support@npmjs.com in CC. If the owner doesn't reply within at least 4 weeks, support acts. A separate route for adopting abandoned packages is mentioned in a community reply, but it is not established, so do not plan around it.
- Hex. The dispute policy covers abandoned and squatted names. If the owners don't respond, you get the name after 30 days if the Hex team agrees.
- crates.io. The team will not transfer an existing crate without the current owner's explicit approval, and RFC 3646 says it will decline every request to mediate. It does remove squatted crates.
- RubyGems. A staff reply says admins do not interfere with ownership unless a gem is proven to be actively harmful. The Adoptions feature has been removed from rubygems.org.
These policies change. Before you start, re-read the live policy pages: PEP 541 and PyPI's name retention docs, the npm policies repository, the Hex dispute policy, and crates.io RFC 3646. Write down the date you read each one.
How do you tell a squatted name from an abandoned or a live one?
A squatted name is held by a package that does nothing. An abandoned name is held by a package that works but whose owner can't be reached and has not released in the registry's window (twelve months on PyPI). A live name has an owner who answers on any channel, however old the last commit is. Your verdict decides which part of the policy you file under, so write it down before you contact anyone.
Each signal proves something narrow and can mislead you in a specific way:
| Signal | What it proves | How it lies |
|---|---|---|
| Last release date | Whether the 12-month PyPI clock has run | No release does not mean no owner |
| Imports and runs | Whether it is a squat | A tiny working package still is not one |
| Downloads | Whether anyone installs it | Mirrors and bots inflate counts |
| Reverse dependencies | Who breaks if the name changes hands | Misses users who pin outside the registry |
| Any reply, any channel | The owner is reachable | A reply on an unlisted channel still counts |
The squat test is binary: install the package, import it, call something. If it does real work, even very little, it is not a squat. One crates.io example cited as non-squatting is wgpu-noboiler, which is small but functional. If it fails, keep the output. That output is the most useful line in a squat filing.
Which verdict, which route
Budget 1 to 2 hours for this stage. When you finish, you have a one-line verdict, the date you checked, and links to the evidence behind it.
The procedure, step by step
The full job is eight steps. Most of the elapsed time sits in steps 4 and 5, and nearly all of it is calendar time, not working time. Start the contact sequence on the same day you finish the trace. Every day you put it off pushes back each window that follows.
Taken name to transfer or rename
- Classify the nameCheck last release date, whether it imports and runs, downloads without mirrors, and reverse dependencies. Write a one-line verdict: squatted, abandoned, or live (1 to 2 hours).
- Confirm the registry routeOn crates.io or RubyGems without owner consent there is no route, so skip to the checkpoint. Write the route down (15 minutes).
- Trace the ownerWork through registry metadata, commit emails, the account's other packages, chat handles, and employer records. Stop at two working channels or a written record of each dead end (1 to 2 days).
- Run a dated contact sequenceEmail with registry support in CC where required (npm, Hex) and open an issue on the project's repo. Send reminders on the same channels until you have three timestamped attempts.
- Wait the registry's windownpm 4 weeks, Hex 30 days. PyPI states no candidate wait, but staff run their own check of up to six weeks after you file.
- File the requestFill in the registry's form, attaching the dated contact log and your classification evidence. Done means an issue number (about 1 hour).
- Check downstream safetyRead downloads without mirrors and reverse dependencies, and plan a first version above the old highest release (half a day).
- Hold the checkpointIf the launch date comes before the realistic decision date, ship under a scoped or new name now and keep the request open.
Who owns each step: the person requesting the name owns steps 1, 2, 4, and 6. A sourcer, or whoever is best at finding people, owns step 3. Engineering owns step 7. The engineering manager owns step 8 and should put its date on the calendar on day 0, not when the wait starts to hurt.
How do you find the owner when the listed email bounces?
Treat the registry's metadata as the first layer of the trace, not the whole of it. When the listed address bounces, log the bounce with its date. Then work outward through the project's docs, its commit history, the account's other packages and chat handles, and finally employer records. Stop when you have two channels that work, or a written record of every dead end.
Owner trace, cheapest layer first
- Registry metadataPyPI profile and Author field emails, npm owner ls, mix hex.owner list
- Project home and docsEmails in the documentation or home page, issues on the repo, PRs if issues are off
- Commit historyAuthor emails on the repo's commits, often a newer address than the registry's
- Linked accountsThe same account's other packages, plus chat handles such as Discord
- Employer recordsPublic professional profiles that tie the handle to a current employer
Registry metadata and project pages
PEP 541 names three addresses, and PyPI staff check them during their own reachability check. They are the profile email, the Author field email, and any email addresses in the project's documentation or home page. On npm, npm owner ls lists the owners. On Hex, mix hex.owner list does the same. Try every address you find, even ones that look stale. A bounce with a date on it is evidence. Skipping an address is a gap in your log.
Repos, chat, and pull requests
People filing these requests already get around dead emails, and the registries accept it. The payjoin request used Discord as well as the Author email. The qubo-solver request used issues on the project's own repo. When the repo has issues turned off, filers have opened a PR to make contact. These channels leave a public, dated trail that staff can check without taking your word for it. That is worth more than a private email nobody else can see.
Employer records
Some owners have moved on to a job and stopped watching the account. The commit history usually gives you a real name and sometimes a company domain. From there, the person's current employer is the most dependable way back to them. Don't expect a job title to find them for you.
Most people who maintain packages do not list it as their job title, so searching by title misses nearly all of them:
| Segment ("Maintainer" title) | Profiles in Refolk's index | Derived ratio |
|---|---|---|
| US, Python | 45 | 15x the US Rust count |
| US, Rust | 3 | Baseline |
| Germany, Python | 8 | US Python is 5.6x this |
Employers among the US Python profiles include Anaconda, Red Hat, NVIDIA, Homebrew, and Kedro. The German profiles include CNCF and Debian. The three US Rust profiles work at Google, Wonder, and Sonatype. The counts are small because titles are the wrong way in. Search on the name from the commits, the package, and the employer instead. This is where Refolk helps: you describe the person in plain English, and it searches public profiles, the public GitHub graph, and the open web together, so you don't have to cross-reference a handle, a commit email, and an employer by hand.
Spend no more than 1 to 2 days on this step. If you reach a person on any channel and they decline, the name is live and you go to the checkpoint. If every layer is a dead end, the written record of dead ends is the deliverable. It becomes the "Contact and additional research" section of your filing.
How long does each registry make you wait?
npm makes you wait at least 4 weeks after you email the owner with support in CC, with extra time allowed around common holidays. Hex makes you wait 30 days, subject to the Hex team agreeing. PyPI states no wait for the person asking. Once you file, though, staff run their own reachability check, which ends after six weeks, and the issue sits in a queue before that check starts.
The contact sequence
Send three attempts, each with a date and a link. One documented PyPI filer sent the initial request, a first reminder 30 days later, and a second reminder 40 days after that, so roughly day 0, day 30, and day 70. That timing covers the npm and Hex windows on the first reminder, and the second reminder shows staff you kept trying.
Dated contact sequence
- Day 0Email every working address, support in CC on npm and Hex, open a repo issue
- Day 30First reminder on the same channels, linking the original; npm and Hex windows have run
- Day 70Second reminder, same channels, same thread where possible
- FileAttach the dated log, classification evidence, and download figures
- Staff checkPyPI runs its own reachability check, ending after six weeks
Filers do not agree on how long to wait before filing on PyPI. The skills request was filed after a single attempt, and the qubo-solver filer waited six months. PEP 541 only requires you to show your own failed attempts to contact the owner. My default is three attempts over about ten weeks. You can file sooner, but that is a judgement call, not a requirement.
Subject: Request to take over the "<package>" name on <registry> Hi <owner name or handle>, I maintain <your project> (<repo link>) and would like to publish it as "<package>" on <registry>. The current "<package>" has had no release since <date of last release>. <One factual line: it does not import / its repo has had no activity since <date>.> Would you be willing to transfer the name to me, or add me as a co-owner? If you still use it, a one-line reply saying so is all I need, and I will choose another name. I am also asking on <other channel, with link>. If I have not heard back, I will follow up here on <date, 30 days out>. Thanks, <your name> <your registry username>
Send the same day on every working channel; on npm and Hex put registry support in CC (support@npmjs.com for npm); keep the follow-up date honest.
On crates.io, add one line asking the owner to consent using the policy's exact wording: "I consent to the transfer of this crate to the first person who asks help@crates.io for it." Because crates.io won't act without consent, this sentence is the only thing that moves the crate.
What goes in the filed request
The PyPI support template asks for the project, your username, your reasons, "Maintenance or replacement?", the source repositories, "Contact and additional research", and agreement to the Code of Conduct. Fill in the research section from your log, not from memory.
Project to be claimed: <package> (<link to the project page>) Your PyPI username: <username> Reasons for the request: - Verdict: <abandoned under PEP 541 / invalid: name squatting> - Last release: <date> (more than twelve months ago) - Owner activity on home page: none since <date> (<link>) - Squat test, if claimed: <command run and its output> Maintenance or replacement?: <Maintenance of the existing project / Replacement with a new project> - First new version will be <x.y.z>, above the highest existing release <a.b.c> Source code repositories URLs: <links> Contact and additional research: - <date>: email to PyPI profile address: <bounced / no reply> - <date>: email to Author field address: <bounced / no reply> - <date>: issue opened on project repo: <link> - <date>: first reminder: <link> - <date>: second reminder: <link> - <date>: <other channel, e.g. chat handle>: <link or description> - Downloads without mirrors: <figure and period> - Reverse dependencies: <count, and links if any> Code of Conduct: [x] I agree to follow the Code of Conduct
Paste into the PyPI support template; every contact line needs a date and a link or a description of the bounce.
How long the PyPI queue actually is
There is no published median time from filing a PEP 541 request to its resolution, so any number you quote is a snapshot. The bot comment on each new issue in the pypi/support tracker shows how many PEP 541 issues are open. Three snapshots:
| Date | Open PEP 541 issues ahead |
|---|---|
| 2026-06-07 | 261 |
| 2026-10-15 | 331 |
| 2026-10-23 | 328 |
That is about 70 more open issues in roughly four months. One case gives a duration: issue #10957 took about 4.5 months to move from Pending to its first reachability step. After that, the six-week staff check can still run. The PyPI support specialist role did once bring the backlog to "current", with about a week to first response and about 500 issues resolved in a year. Before that, the backlog was a year and four months behind. The backlog swings because one specialist works through issues that keep arriving, and the six-week check comes on top of whatever the queue wait is. To re-check, open a fresh issue in the tracker and read the bot comment.
How this goes wrong
Most failed claims come from one of seven mistakes. Each one either has the registry reject the request or ends with you taking a name that still had users. These are the parts of the method most worth getting right.
- Treating "inactive" as "abandoned". No commits doesn't mean no reachable owner. PyPI will not reassign a name against an owner who can be reached and says no. Check whether there has been any reply on any channel, including ones the owner never listed.
- A false positive on the squat test. A small package that works is not a squat. The crates.io example cited as non-squatting, wgpu-noboiler, is exactly that kind of package. Check that you actually installed, imported, and ran it.
- Reading downloads as real use. Mirrors and bots inflate download counts. JFrog's empty placeholder packages still drew about 200,000 downloads in three months. Use pypistats figures without mirrors on PyPI, and always read reverse dependencies alongside them.
- Contact attempts with no dates. A request that only says "contacted, no reply" gives staff nothing to check, so they have to redo your work. Every attempt needs a date and a link, or a dated note of the bounce.
- Assuming the wrong registry policy. A crates.io mediation request will be declined. A RubyGems request for an abandoned gem has no published process behind it. Before writing anything, check the gate in step 2.
- Waiting in the PyPI queue. About 330 issues are open, and the first staff action in #10957 took about 4.5 months. A launch date that depends on the queue is a launch date you don't control.
- Version collision after the name is reused. Old versions stay installable, so a user who pinned one may get the old project's code or yours, depending on how they pinned. Make your first new release higher than the old highest version.
Is it safe to take a name that still gets downloads?
A name that still gets real downloads or has reverse dependencies is not safe to take until you know who is installing it and what they will get afterwards. PEP 541 requires download statistics showing the project is not being used before a name is reused. crates.io only allows an owner to delete a crate when it has a single owner, fewer than 500 downloads a month, and no other crate depends on it.
The risk is not hypothetical. JFrog's Revival Hijack research, by Andrey Polkovnychenko and Brian Moussalli, found the pingdomv3 name re-registered the same day its original owner removed it. They estimated about 309 PyPI packages are removed each month and that 22,000 removed names were at risk. Installers trust the name, not the owner. So when a name changes hands, every unpinned install picks up the new code without anyone deciding to.
Deleting a package does not retire its name. It hands the name to whoever registers it next.
Three things follow for the downstream check (half a day of engineering time):
- Ask for a transfer, never a deletion. A deletion opens a gap that anyone can fill before you do. RubyGems reserves the names of deleted gems for a while; one gem page showed "71 more days", but the full length of that period is not established.
- Number your versions above the old ones. On PyPI and npm, old releases stay where they are. For Hex, a forum post says old versions remain after a takeover and the new owner can only publish new ones. The author's role is not verified, so confirm it against the current dispute policy before you rely on it.
- Tell existing users. If reverse dependencies exist, open an issue or PR on each one before your first release, and link it in your filing as evidence that you thought about the people downstream.
When should you stop waiting and rename or scope?
Stop waiting the day you can see that the launch will come before the realistic decision date. Ship under a scoped or new name and keep the request open. Treat the checkpoint as a date set on day 0, not a feeling that sets in after a few months.
For each registry, the realistic decision date is roughly:
- npm: 4 weeks from the first message with support in CC, plus whatever time support takes to act.
- Hex: 30 days, if the Hex team agrees.
- PyPI: queue time plus up to six weeks for the staff check. In the one documented case, the first reachability step came about 4.5 months after filing. That is one case, not a forecast, so read the current queue count before you set the date.
- crates.io and RubyGems: never, unless the owner consents. The crates.io consent sentence is the only route there. That is why a rename is cheaper on these two registries than a dispute. On RubyGems, staf became "staf4ruby" after the owner did not reply.
The fallback options differ by registry:
- npm has scopes. Publish as
@yourscope/namewithnpm publish --access=public. Developer-relations leads already publishing under a scope can usually ship there the same day. - Hex organisations do not create namespaces. All public packages still share one global namespace, so the fallback is a new name, not a prefix.
- PyPI blocks near-variants: names that differ only by dashes, underscores, and dots count as too similar. Pick a name that really is different.
Nobody has published what a migration actually costs. The only evidence is what filers say, such as the fluxy filer's claim that renaming "would require massive changes". If your team says the same, write down specifically what would change: import paths, docs, config keys. Then compare that list with the wait. Usually it is shorter than it sounds.
Keeping the claim current after you file
After you file, the job is keeping the record and the checkpoint up to date. Re-read the open count when you check your issue. Answer staff questions within a day, because a slow reply can be read as you not being reachable. Keep logging anything new from the owner, with a date. If the owner replies at any point, even to say no, add it to the issue at once. The name is then live, and what you do next is a negotiation or a rename.
If the owner turns up working somewhere else, a fresh search on their name and the employer from their commits is quicker than starting the trace again. Refolk keeps that search to one plain-English request rather than another two days of manual cross-checking.
Before you call the job done
- The written verdict (squatted, abandoned, or live) has a date and links to the evidence behind it.
- The registry route was checked against the live policy page, and the date you read it is recorded.
- At least two working owner channels were tried, or every dead end is written down with a date.
- The contact log has three attempts, each with a date and a link or a dated bounce note.
- On npm and Hex, registry support was in CC from the first message and the 4-week or 30-day window has passed.
- The filed request has an issue number, and the research section was built from the log.
- Downloads were read without mirrors, and reverse dependencies were checked and notified.
- The first planned release is higher than the old highest version.
- The checkpoint date is on the engineering manager's calendar, with the fallback name or scope already chosen.
Questions practitioners ask
How long does a PEP 541 request take?
Nobody has published a median time from filing to resolution, so plan from evidence. In one documented case, a request filed in June took about 4.5 months just to move from Pending to its first reachability step, and the staff reachability check can then run for up to six weeks. The open queue has swung from current, with about one week to first response, to over 300 issues. Read the bot comment on a fresh issue for today's count.
Can I get an npm package name taken by an inactive owner?
Yes, at npm support's discretion, but inactivity alone is not the test. Email the owner with support@npmjs.com in CC, and if there is no reply after at least 4 weeks (longer around holidays), support will address the request. A package with no genuine function counts as squatted. A route for adopting abandoned packages has been described in a community reply, but it is not established, so do not plan around it.
Can crates.io transfer a crate name from an unreachable owner?
No. The crates.io team will not transfer an existing crate without the current owner's explicit approval, and RFC 3646 says it will decline every request to mediate. The team does remove squatted crates. If you reach the owner, they can consent using the policy's exact sentence. If you cannot reach them, renaming is cheaper than waiting, because there is no route that works without consent.
What counts as name squatting on PyPI and npm?
On PyPI, a package with no functionality, or an empty one, is invalid as name squatting and can be removed. On npm, a package is squatted if it has no genuine function. A small package that works is not a squat, however little it does. Before calling it a squat, install it, import it, and run something. Keep that output for your filing.
What do I do when the owner's listed email bounces?
Log the bounce with its date, then keep tracing. PEP 541 lists three addresses: the profile email, the Author field email, and any email in the project's documentation or home page. Past those, use author emails from the commit history, issues on the project's repo (or a PR if issues are turned off), chat handles such as Discord, and employer records. Every attempt needs a date and a link.
Should I ask the owner to just delete the package so I can register it?
No. Deleting a package frees the name for anyone, and installers trust the name, not the owner. JFrog's Revival Hijack research found pingdomv3 re-registered the same day its original owner removed it. Ask for a transfer or a co-owner invitation instead. On crates.io, ask for the exact consent sentence, which lets the registry hand the crate over directly.
Try it on the search you came here for
Stop building boolean strings. Just describe the person.
Type one sentence. I plan the search, read GitHub, public LinkedIn and Crunchbase records, and the open web as it is right now, and hand back a ranked list with the reason next to every name.
01Describe them
One plain sentence. Role, city, stack, stage, whatever matters to you.
02I read the web live
GitHub, public LinkedIn and Crunchbase records, the open web. Not a database that went stale last quarter.
03You read the shortlist
Ranked, with the reasoning under every name. Open a profile, ask a follow-up, narrow it down.
- Staff backend engineers in NYC who shipped Rust in production
- Series A fintechs in SF under 50 people, growing headcount this year
- Maintainers of fast-growing Rust web frameworks on GitHub
- No boolean, no filters, no seat to buy. One box.
- Read at search time, so a profile updated yesterday counts today.
- Every step visible as it runs, every name with its reason.
500 free credits on sign-up. No card, no demo call. See real searches.