Toggle menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.


From the unofficial Signal Wiki

This article is about the upcoming user-facing Usernames feature. "Username" may also refer to other concepts.

Usernames are a feature that allows you to set a username that others can use to find you on Signal without necessarily knowing your phone number. It should not be confused with the Phone Number Privacy feature—by itself, setting a username will not hide your phone number from others (by default, your phone number is hidden, but this setting can be changed irrespective of your username settings). In order to hide your phone number from others, you need to use the aforementioned Phone Number Privacy feature.

Usernames are only used for establishing a connection, and are not a replacement for the display name that is part of your profile.[8] They are usually not displayed in other people's clients, except for certain situations where there is nothing else to display (such as when you start a new chat with someone by username and they haven't accepted the request yet).[9] After a connection is established, they are discarded by the client.[10]

Usernames are kept for a few days after account deactivation,[11] and can be restored after re-registering.[12] Starting March 2024, the last three usernames are also kept for a few days after releasing or switching.[13]

Privacy[edit | edit source]

  • "Usernames [...] aren’t shared on your profile".[14] This means that while people can use your current username to start a chat with you if they know it at that point, people can't see your past, current, or future usernames. Additionally, once a profile name is known for a user, the client deletes the username saved for that user from the local record.[15][10]
  • The username itself is not visible to the server at any point. Given a phone number, Signal cannot tell you a person's username (the other way around, however, is possible to do on the server).[16]
  • The username hash to UUID / ACI mapping is stored on the server in plain text.
  • Signal apps can not make authenticated requests to the server to look up a user by their username hash[17] or look up a username link handle[18] (such requests will be rejected). In other words, these requests must be unauthenticated, thereby improving privacy, as the Signal server only sees the IP address, Signal version (from the user agent), but does not directly see who is looking up a specific username hash or username link handle. See Usernames#Username links for more details about different kinds of links.

Format[edit | edit source]

Usernames have the following format: nickname.discriminator, e.g. nickname.12345.[19]

Nickname[edit | edit source]

The nickname is set by the user. It:

  • Contains only alphanumeric characters (a-z, A-Z, and 0-9) or underscores (_).[20]
    • Under the hood, Signal uses the lowercase version, however.[21] In other words, a nickname may be displayed as NickName in the UI for you (for example, when you use someone's username link),[22] but is treated as nickname. Usernames with the same normalized (lowercased) nickname can coexist, but they must have different discriminators. For example, NickName.123 and nickname.1234 can be used by two different accounts at the same time, but NickName.12 and nickname.12 can not.
  • Does not start with a number (0-9).
  • Has a minimum length that can be configured remotely using the global.nicknames.min feature flag, but defaults to 3 characters.[23]
  • Has a maximum length that can be configured remotely using the global.nicknames.max feature flag, but defaults to 32 characters.[24]
    • Technically the cryptography-related functions support up to (but not including) 48 characters.[25]

Discriminator[edit | edit source]

The discriminator serves the purpose of making one's username more private and less accidentally discoverable.[26]

  • Contains only numbers (0-9).
  • Can't have leading zeros except for the case where there is only one significant digit.[27]
  • Minimum length of 2 digits (starting from 01).
  • Maximum length of 10 digits.[28] However, the only 10-digit discriminator allowed appears to be 1000000000 (1 000 000 000, 109).[29]

The discriminator was generated randomly by the client (app) and couldn't be chosen by the user directly,[note 2][note 3] but this has now changed and you can choose it yourself. The following section describes the generation process before this change.[30][31]

Generation (old)[edit | edit source]

The process of setting a username (which includes the discriminator generation) looks like this:[32][33]

  1. Once a nickname is provided, the discriminator generator starts with the length of 2 digits.
    • When it generates a discriminator of the initial width (2), rather than generating a number from 10 to 100 (like one might expect for a 2-digit discriminator), it generates from 1 to 100. So the discriminators may be 1- digit as well. Although if the generated discriminator's length is less than the initial width, it is left-padded with zeros, e.g. nickname.01 instead of nickname.1.[34]
  2. It generates 4 random discriminators of the initial length.
  3. Then it increases the discriminator length and generates 3 discriminators. This continues up to (and including) a discriminator of 9 digits.
    • There are a total of 20 discriminators generated. This matches up with the maximum amount of username hashes the server accepts for a given reservation attempt.[35]
    • The number of attempts may change between attempts. See the table in the 2023 section for a visual overview.
  4. The client (app) sends a list of username hashes, all with different discriminators, to the server.
  5. The server checks each username hash one by one to see if it happens to be available. If an available username hash has been found, the username is reserved[36] for the user for a short amount of time (5 minutes)[32] to allow them to confirm that they would like to set a username with the provided discriminator.
    • If an available username hash has not been found, the username is shown as not available to the user.[note 3]
  6. When (if) the user confirms the username, the server validates the associated zero-knowledge proof that the client provides.[37]
    • The proof proves to the server that you know the nickname and discriminator pair that produced the username hash you provided.[38]

Username links[edit | edit source]

There appear to be two distinct link types being developed.

However, it's possible that the new Username link type will replace the previously developed hash-based link, and the server API endpoints used to look up users by their username hash will only be used if you manually type in a username to look up in Signal.

Username link[edit | edit source]

This link is not based on your username. Rather, it will contain a (random) UUID (not the account UUID, ACI, or PNI) called a username link handle[39] that simply points to your encrypted username stored on the server.[40] Since the username is encrypted (by your app before uploading it to the server to activate the link), it is likely the link will also contain a (random) key to decrypt the username (this key does not need to be submitted to the server).

As such, this link can be created, updated, and deleted independently of your username. This means it may be intended for use as a temporary, throwaway link that you can share with someone without revealing your username or its hash directly (it will only be revealed to them once they look it up). When you delete the link, it can no longer be used to look up your encrypted username and hence contact you in any way and is thus rendered completely useless.

You must have a username set up to activate such a link. You can only have one username link active at a time.[40]

The username that is encrypted keeps the case you chose,[22] so the user that uses the link will see the username exactly as you chose it, even though usernames are fundamentally case-insensitive.

Hash-based link[edit | edit source]

This link contains the hash of your username. As such, it can only change if you change your username, and you can only have one such link active at a time.

See the Username-based section of the URLs article for more details on the URL format of this link.

Development history and timeline[edit | edit source]

Usernames have undergone multiple changes while they were in development. Additionally, some timelines for release have been communicated. Some of these changes and timelines are listed below. Note that this list does not include development of related features such as UUIDs / ACIs / PNIs, phone number privacy.

See also: URLs#Change history.

2019[edit | edit source]

  • 2019-08-08[41] (or at least as early as 2019-08-15[6]): Development begins, usernames do not have any kind of discriminator.
  • 2019-09-25: A way to reserve (in current terminology, prohibit, as reserving is now a part of the process of setting a username as described in Generation) usernames to be only settable by certain users is implemented.[42]
  • 2019-10-28: Usernames can no longer start with a number.[43]

2022[edit | edit source]

  • 2022-08-15: Support for discriminators is added.[44]
  • 2022-09-07: Approximate timeline of release, "early 2023 at the latest", is communicated.[45]
  • 2022-09-14: Discriminator separator changed from # to .. Initial discriminator width changed from 4 to 2. [46]
    • The change to the separator may have been done in part because, due to the URL format at that time, the # would be URL-encoded for links into %23, which would have made it harder to visually discern the discriminator (e.g.
    • The following table shows how the discriminator generation changed due to the initial width change. There will be more chances to get a shorter discriminator (and 20 more attempts to randomly find any available discriminator in general). Note that despite this, the total amount of available discriminators for a given nickname (109 - 1 = 999 999 999) hasn’t changed.
Discriminator generation change #1 overview
Attempts to find available discriminator Previous configuration New configuration
10 nickname#0001 or nickname#0012 or nickname#0123 or nickname#1234 nickname.01 or nickname.12
10 nickname.123
10 nickname.1234
10 nickname#12345 nickname.12345
10 nickname#123456 nickname.123456
10 nickname#1234567 nickname.1234567
10 nickname#12345678 nickname.12345678
10 nickname#123456789 nickname.123456789
  • 2022-10-19: Approximate timeline of release, "first half of 2023", is communicated.[47]
  • 2022-11-10: Based on code, it is expected that usernames will be released together with phone number privacy.[48]
  • 2022-12-13: Usernames are now case-sensitive,[49] but uniqueness checks etc. use the lowercase version.

2023[edit | edit source]

  • 2023-02-012023-02-09: Implementation transitions to username hashes that use zero-knowledge cryptography.[50]
    • Nickname minimum and maximum length is now configured using remote feature flags.[51]
    • The value stored on the server is now the username hash, not the plain text username.
    • Due to this change it's likely no longer possible for the server to prohibit certain nickname patterns (i.e. make them only settable by certain accounts that they have been assigned to),[52] forbid certain discriminators,[53] or create usernames without discriminators through some "out-of-band" mechanism,[54] which was all possible before.
    • Discriminator generation is now performed client-side. (See the updated Generation section.)
    • Discriminator generation attempts[note 4] changed as illustrated by the following table.
Discriminator generation change #2 overview
Patterns Before: attempts to find available discriminator After: "attempts" to find available discriminator[note 4][55]
nickname.01 or nickname.12 10 4
nickname.123 10 3
nickname.1234 10 3
nickname.12345 10 2
nickname.123456 10 2
nickname.1234567 10 2
nickname.12345678 10 2
nickname.123456789 10 2
Total attempts 80 20
  • 2023-04-11: References in the code to prohibited usernames are removed,[56] thus confirming that it's no longer possible for the server to prohibit certain nickname patterns, as mentioned above.
  • 2023-06-02: "Username links" introduced in the server code in addition, or to replace hash-based links.[57] Additionally, more server API documentation was added, and some integration tests were added too.[58] See Usernames#Username links for more details.
  • 2023-10-05: Approximate timeline of release, "early 2024", is communicated.[59]
  • 2023-11-08: Public username testing begins in the staging environment.[60]

2024[edit | edit source]

  • 2024-01-09: You can now pick any custom discriminator in the app (currently, iOS and Android only) and attempt to reserve and claim it if it's available.[30][31]
  • 2024-01-18: The new implementation with zero-knowledge cryptography now makes use of case-sensitive nicknames, but does so just for the username people see when using your username link.[22] Under the hood the username is still lowercase-only and that's what determines its uniqueness.
  • 2024-02-20: Usernames and phone number privacy are now available in beta and are officially announced.[1]
  • 2024-05-05: Usernames and phone number privacy are now available to everyone.[2]
  • 2024-03-06: After releasing or switching from an existing username, other people can't claim it for seven days. Up to three usernames may be saved for an account that way.[13]

Notes[edit | edit source]

  1. In 6.2.0, no longer used; instead, the feature flag for phone number privacy, android.pnp, decides whether the feature is active github:signalapp/Signal-Android/commit/a2415261bd39092020a7e02b402ad20878808212
  2. However, it may be possible to create a custom build of Signal which would allow choosing a discriminator, or more precisely a set of discriminators (any of which you'd accept) to submit to the server, manually.
  3. 3.0 3.1 It is likely possible to re-attempt the whole process of discriminator generation (in hope of getting a discriminator that's available) by changing the username (and then restoring the previous one) in the input field in the app.
  4. 4.0 4.1 Note that attempts after this change have a slightly different meaning. They now represent the distribution of nicknames submitted by the app to the server all at once, rather than the number of times the server tries to generate each discriminator consecutively. However, as the server appears to check availability of the provided username hashes consecutively, it still can be considered an "attempt".

References[edit | edit source]

  1. 1.0 1.1 forum:t/59024
  2. 2.0 2.1 Phone number privacy and usernames are now rolling out to everyone using Signal version 7.0! Update your app to take advantage of these new features 🎇post by @[email protected], 2024-03-05
  3. forum:t/59027
  4. forum:t/59023
  5. github:signalapp/Signal-Android/commit/608815a69b78000345ef39510c71014ccbfd3003
  6. 6.0 6.1 github:signalapp/Signal-iOS/commit/5ce5264d074061080ea0eb7da31f3ae17226c384
  7. github:signalapp/Signal-Desktop/commit/3190f95fac724ab0c1a30cb5b7e0213d918aa25f
  8. "[in reply to 'If I have someones phone number and they have Signal. Can I start a chat with them with my username?'] You can start a chat with them via their username. If you start the conversation with them, they will not see your username. Usernames are not part of your profile — they’re just entrypoints for other people to start chats with you."post #73 by greyson-signal in Beta feedback for the upcoming Android 7.0 release
  9. "[T]here are some (expected, unavoidable) situations where all we have to render for a person is a username. The most obvious one is when you start a new chat by username. At the top of the chat, we have to show who you sent the message to."post #92 by greyson-signal in Beta feedback for the upcoming Android 7.0 release
  10. 10.0 10.1 "I agree with claim that usernames can change hands and therefore cached data can go stale. This is why as soon as we learn the profile name for a user, we delete their username from our local recipient record."post #92 by greyson-signal in Beta feedback for the upcoming Android 7.0 release
  11. forum:t/59075/8
  12. "Add support for restoring usernames post-registration."
  13. 13.0 13.1 github:signalapp/Signal-Server/commit/3cc740cda3e2811fbac1ce07d4b2e0bc6e2bff20
  14. Signal iOS: Localizable.strings#L7132-L7133
  15. Signal Android: Github:signalapp/Signal-Android/blob/940cee0f30d6a2873ae08c65bb821c34302ccf5d/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.kt#L268
  16. forum:t/59024/92
  21. libsignal/rust/usernames/src/ "The mapping is only defined for the characters matching [_0-9a-z]"
  22. 22.0 22.1 22.2 "Add support for changing visible username case"
  23. RemoteConfigManager.swift#L252-L255
  24. RemoteConfigManager.swift#L257-L260
  25. libsignal/rust/usernames/src/
  26. strings.xml#L1987-L1991
  28. UsernameUtil.kt#L12
  30. 30.0 30.1 "Allow for picking a custom username discriminator"
  31. 31.0 31.1 "Add ability to set custom username discriminators."
  32. 32.0 32.1
  34. github:signalapp/Signal-Server/commit/1891622e69b10c3b8affe9ded2b97ee1ebc74b9e
  36. github:signalapp/Signal-Server/commit/4032ddd4fd9c21b32d1c2469d2d93986362b7d5c
  38. forum:t/9157/889
  40. 40.0 40.1 /username_link endpoint documentation in
  41. github:signalapp/Signal-Server/commit/99c228dd6dde7029798504c3af32739828ff8c02 (commit on GitHub has the date 2019-11-20, but cloning the repository and looking at the commit yields the timestamp of 2019-08-08 when converted to UTC)
  42. github:signalapp/Signal-Server/commit/523134f24bfd4910616511da50fe769d167bbb60 (commit on GitHub has the date 2019-11-20, but cloning the repository and looking at the commit yields the timestamp of 2019-09-25 when converted to UTC)
  43. github:signalapp/Signal-Server/commit/2b987e6e9301a290648ccc77402172b275083933 (commit on GitHub has the date 2019-11-20, but cloning the repository and looking at the commit yields the timestamp of 2019-10-28 when converted to UTC)
  44. github:signalapp/Signal-Server/commit/a84a7dbc3d7d7a519e3ef9c080c07d97befd4758
  45. [1] via forum:t/9157/624
  46. github:signalapp/Signal-Server/commit/d0a8899daf3f9771bba87a3c1ea527b6c96d8d6b
  48. github:signalapp/Signal-Android/commit/a2415261bd39092020a7e02b402ad20878808212
  49. github:signalapp/Signal-Server/commit/26f5ffdde34ec2941f6c6c1f07be9ee3380d2569
  50. github:signalapp/libsignal/commit/731964f46838c1f26ca1848579b9ee80ffeb14f3
  51. UsernameSelectionViewController.swift#L30-L34
  55. libsignal/rust/usernames/src/
  56. signalapp/Signal-Server commit 61af1ba02
  57. signalapp/Signal-Server/commit/47cc7fd615fe5d159953190b546e199aac955df9
  58. signalapp/Signal-Server/commit/e6917d8427e272046e70c723c02e60b5c3f63a78
  59. "How do organizations like Signal sustain in an environment of mass surveillance" by Meredith Whittaker (Hasgeek TV). (Credits to post #1276 by QuickBanana in Usernames in Signal, post by u/Strength6092 on Reddit.)
  60. "After rounds of internal testing, we have hit the point where we think the community that powers these forums can help us test even further before public launch."post #1 by jimio in Public Username Testing (Staging Environment)
Cookies help us deliver our services. By using our services, you agree to our use of cookies.