HKP and /pks/lookup: how keyserver requests work

Updated November 2026

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.

gpg --recv-keys FPR dirmngr reads dirmngr.conf keyserver GET /pks/lookup?op=get ASCII-armored key returned; gpg keeps only self-signatures by default
A key fetch over HKPS: gpg hands the job to dirmngr, which asks the keyserver over HTTPS.

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.

Variables of the legacy /pks/lookup interface
VariableValuesMeaning
opgetReturn the matching key(s), ASCII-armored.
opindexReturn a list of matching keys.
opvindex"Verbose index": historically the list plus the signatures on each key. Deprecated in the current draft.
searchtext or 0x+hexWhat to look for. A leading 0x means a key ID or fingerprint; anything else is a text search of the user IDs.
optionsmr, nmmr = machine-readable output for programs. nm = "no modification", for uploads: fail rather than let the server alter the key.
fingerprinton/offShow fingerprints in an index.
exacton/offExact 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:

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

How GnuPG maps keyserver URLs to connections (GnuPG 2.4, tested November 2026)
You writeGnuPG connects toNotes
hkps://keys.openpgp.orgHTTPS, port 443Recommended
hkp://keyserver.ubuntu.comHTTP, port 11371No encryption; blocked by many firewalls
hkp://keyserver.ubuntu.com:80HTTP, port 80Old firewall workaround; still unencrypted
subkeys.pgp.net (no scheme)HTTP, port 11371Treated 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:

One key, three ways of naming it
FormLengthExample
Fingerprint (v4)40 hex digitsF6ECB3762474EDA9D21B7022871920D1991BC93C
Long key ID16 hex digits871920D1991BC93C
Short key ID8 hex digits991BC93C

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.

How servers differ

Not every server supports the whole interface. As of November 2026:

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