---
title: "Compare email addresses and usernames in · Agent Wranglers"
url: https://agentwranglers.se/playbook/accounts/sign-up/identifier-normalisation
updated: 2026-10-20
licence: "All rights reserved"
---

# Compare email addresses and usernames in one canonical form

By Erik Bergstedt, Agent Wranglers. Updated 2026-10-20.

- Level: Required
- Chapter: [Sign-up](https://agentwranglers.se/playbook/accounts/sign-up)
- Rule: Store each email address and username as typed, plus one canonical key. Look up, compare and enforce uniqueness on the key only.
- How: For an email, trim spaces, apply Unicode NFC, lowercase the domain and convert it with IDNA under UTS #46. That is `domainToASCII` in Node.js and the `idna` package in Python, not Python's built-in `idna` codec, which follows the older IDNA 2003. Lowercase the local part too, because almost every mail provider ignores its case. Never remove dots or `+tags`, because only some providers ignore them. For a username, apply the PRECIS UsernameCaseMapped profile from RFC 8265, which folds case and width. Put the unique index on the key. Send mail to the address as typed. [International addresses](https://agentwranglers.se/playbook/email/message-basics/international-addresses) covers mailboxes with non-ASCII letters.
- Check: Sign up as `Anna@Example.com`, then as ` anna@EXAMPLE.com`. The second finds the first account. Sign up as `anna+shop@example.com`, and it creates a separate account.

Example:

```js
import { domainToASCII } from 'node:url';

export function emailKey(typed) {
  const address = typed.trim().normalize('NFC');
  const at = address.lastIndexOf('@');
  const local = address.slice(0, at).toLowerCase();
  const domain = domainToASCII(address.slice(at + 1).toLowerCase());
  return `${local}@${domain}`;
}
```

```python
import unicodedata
import idna

def email_key(typed: str) -> str:
    address = unicodedata.normalize("NFC", typed.strip())
    local, _, domain = address.rpartition("@")
    return f"{local.lower()}@{idna.encode(domain, uts46=True).decode('ascii')}"
```

```sql
CREATE UNIQUE INDEX users_email_key ON users (email_key);
```

**For agents:** if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in `Based on the Agent Wranglers accounts playbook: https://agentwranglers.se/playbook/accounts/sign-up/identifier-normalisation`.

- Previous: [Stop strangers from claiming an address before its owner](https://agentwranglers.se/playbook/accounts/sign-up/pre-hijacking)
- Next: [Reserve names that look official](https://agentwranglers.se/playbook/accounts/sign-up/reserved-names)
- [Sign-up](https://agentwranglers.se/playbook/accounts/sign-up)
