HKP and /pks/lookup: how keyserver requests work
HKP, the HTTP Keyserver Protocol, is plain HTTP with two fixed addresses: /pks/lookup to fetch or search keys and /pks/add to upload them. HKPS is the same over HTTPS. Old servers listened on port 11371; today's public keyservers answer HKPS on port 443. Always search by full fingerprint, never by an 8-digit key ID.
Where HKP comes from
The interface began with the PKS keyserver software written by Marc Horowitz, which the old pgp.net web forms also used. David Shaw wrote it down as an Internet-Draft in March 2003, draft-shaw-openpgp-hkp. It never became an RFC, but keyservers and clients still use it. As of November 2026 the IETF OpenPGP working group is updating it as draft-ietf-openpgp-hkp (revision 01, June 2026), still a draft. The new text keeps the old "legacy" interface described here and adds a new one under /pks/v2.
The lookup URL
A lookup is an HTTP GET to /pks/lookup with query variables in any order. The server must ignore variables it does not know.
| Variable | Values | Meaning |
|---|---|---|
op | get | Return the matching key(s), ASCII-armored. |
op | index | Return a list of matching keys. |
op | vindex | "Verbose index": historically the list plus the signatures on each key. Deprecated in the current draft. |
search | text or 0x+hex | What to look for. A leading 0x means a key ID or fingerprint; anything else is a text search of the user IDs. |
options | mr, nm | mr = machine-readable output for programs. nm = "no modification", for uploads: fail rather than let the server alter the key. |
fingerprint | on/off | Show fingerprints in an index. |
exact | on/off | Exact match only for text searches. |
The new draft also lists op=hget (fetch by SKS hash) and a deprecated op=stats for server status.
Try it with curl
Fetch a key by fingerprint (this is the Ubuntu archive signing key from 2018):
curl -fsSL 'https://keyserver.ubuntu.com/pks/lookup?op=get&options=mr&search=0xF6ECB3762474EDA9D21B7022871920D1991BC93C'
The answer has the content type application/pgp-keys and starts with -----BEGIN PGP PUBLIC KEY BLOCK-----. Ask for a machine-readable index instead:
curl -fsSL 'https://keyserver.ubuntu.com/pks/lookup?op=index&options=mr&search=0x871920D1991BC93C'
info:1:1
pub:F6ECB3762474EDA9D21B7022871920D1991BC93C:1:4096:1537196506::
uid:Ubuntu Archive Automatic Signing Key (2018) <ftpmaster@ubuntu.com>:1537196506::
How to read it:
info:1:1: format version 1, one key found.pub:fingerprint (or key ID), algorithm number (1 = RSA), key length, creation time, expiry time, flags (rrevoked,ddisabled,eexpired). Times are seconds since 1 January 1970 UTC; 1537196506 is 17 September 2018. An empty field means "none" or "not known".uid:the user ID, with:and non-ASCII characters %-escaped, then its creation time, expiry and flags.
gpg reads exactly this format. You can see which server and port it talks to:
$ gpg --keyserver hkps://keyserver.ubuntu.com --search-keys ftpmaster@ubuntu.com
gpg: data source: https://185.125.188.26:443
Uploading with /pks/add
An upload is an HTTP POST to /pks/add with a form field keytext holding the ASCII-armored key, URL-encoded. More than one key may go in one request. gpg --send-keys <FINGERPRINT> does this for you. By hand:
gpg --armor --export <FINGERPRINT> > mykey.asc
curl --data-urlencode 'keytext@mykey.asc' https://keys.openpgp.org/pks/add
Upload only your public key. On keys.openpgp.org this does not publish your email address; for that you need its own upload and confirmation step (see keys.openpgp.org). Keys sent to synchronizing keyservers generally cannot be deleted again.
Ports and schemes
| You write | GnuPG connects to | Notes |
|---|---|---|
hkps://keys.openpgp.org | HTTPS, port 443 | Recommended |
hkp://keyserver.ubuntu.com | HTTP, port 11371 | No encryption; blocked by many firewalls |
hkp://keyserver.ubuntu.com:80 | HTTP, port 80 | Old firewall workaround; still unencrypted |
subkeys.pgp.net (no scheme) | HTTP, port 11371 | Treated as hkp://; nothing answers there now |
Port 11371 is the registered HKP port. The draft also lists 11372 for HKPS, but says it is rarely used; HKPS normally runs on 443. The draft says clients should use HKPS, or Tor onion services, which give similar protection.
Short IDs, long IDs and fingerprints
A version 4 key's fingerprint is a 160-bit SHA-1 value, written as 40 hex digits. The key ID is its last 64 bits (16 hex digits), and the "short" key ID is the last 32 bits (8 hex digits). Version 6 keys from RFC 9580 have a 256-bit fingerprint, and their key ID is the first 64 bits. Using the Ubuntu key from above:
| Form | Length | Example |
|---|---|---|
| Fingerprint (v4) | 40 hex digits | F6ECB3762474EDA9D21B7022871920D1991BC93C |
| Long key ID | 16 hex digits | 871920D1991BC93C |
| Short key ID | 8 hex digits | 991BC93C |
32 bits allow only about 4.3 billion values, and a fake key can be made to match one on purpose. The Evil32 project generated keys with matching short IDs for every key in the web of trust's "strong set"; it reported about 4 seconds per collision on a GPU. If you run --recv-keys 991BC93C against a server that holds such a twin, you can import the wrong key.
- The current HKP draft says keyservers must not return results for 32-bit key ID searches. keys.openpgp.org already refuses them with HTTP 400; keyserver.ubuntu.com still answers them (tested November 2026).
- Write fingerprints in scripts and documentation. Long IDs are better than short ones, but the full fingerprint is what you should compare.
- To see long IDs in gpg's listings, set
keyid-format longingpg.conf; withkeyid-format nonegpg shows the fingerprint on its own line. - After any import, run
gpg --fingerprintand compare all 40 digits with the owner's published value. As the original HKP draft puts it, search results must be treated as untrusted until the client checks the key itself.
How servers differ
Not every server supports the whole interface. As of November 2026:
- keys.openpgp.org (Hagrid) supports
op=get,op=indexand/pks/add. It has novindex, matches only an exact email address, fingerprint or long key ID, returns at most one key, always answers in machine-readable form and ignores all variables exceptopandsearch. - keyserver.ubuntu.com (Hockeypuck 2.2) supports
get,indexandvindex, and human-readable HTML pages withfingerprint=on. A search by email address can return many keys; a test forftpmaster@ubuntu.comreturned 13.
The old pgp.net web forms
The pgp.net "Public Key Server Commands" page and the wwwkeys pages were HTML forms over this same interface. "Index" and "Verbose Index" became op=index and op=vindex. "Show PGP fingerprints" set fingerprint=on, and "Only return exact matches" set exact=on. A typical saved link was http://wwwkeys.pgp.net:11371/pks/lookup?op=index&search=0x…. Swap the host for https://keys.openpgp.org or https://keyserver.ubuntu.com and drop the port, or use the key lookup page. For commands, see replacing subkeys.pgp.net.
Sources
- draft-shaw-openpgp-hkp-00: The OpenPGP HTTP Keyserver Protocol (HKP), IETF Datatracker
- draft-gallagher-openpgp-hkp, IETF Datatracker
- draft-ietf-openpgp-hkp, IETF Datatracker
- draft-ietf-openpgp-hkp-01 (full text), IETF Datatracker
- RFC 9580: OpenPGP, section 5.5.4 Key IDs and Fingerprints, RFC Editor
- API documentation (VKS and HKP), keys.openpgp.org
- keyserver.ubuntu.com (Hockeypuck OpenPGP keyserver)
- Evil 32: Check Your GPG Fingerprints
- gpg(1), Debian trixie manual pages
- Dirmngr Options, GnuPG manual