HTML <keygen> Tag

Beginner
⏱️ 6 min read
📚 Updated: Jun 2026
🎯 4 Examples
Legacy Security

What You’ll Learn

By the end of this tutorial, you’ll understand the historical <keygen> element and what to use instead for modern web security.

01

Historical Syntax

How <keygen> generated RSA key pairs inside forms.

02

Obsolete Attributes

Understand legacy name, challenge, and keytype.

03

Deprecated Status

Why <keygen> was removed from the HTML Living Standard.

04

keygen vs Web Crypto

Compare the legacy tag with the JavaScript Web Crypto API.

05

Modern Replacement

Use crypto.subtle, HTTPS, and WebAuthn for real auth.

06

Security Best Practices

Never rely on obsolete HTML for encryption or login.

What Was the <keygen> Tag?

The <keygen> element was a specialized form control that generated a public/private key pair in the browser. When the form was submitted, the public key was sent to the server while the private key stayed on the client machine.

⚠️
Obsolete — Use Web Crypto + HTTPS

Do not use <keygen> in new projects. It was removed from the HTML Living Standard. Modern browsers no longer support it. Use the Web Crypto API, TLS/HTTPS, and standards like WebAuthn for authentication.

In the late 2000s and early 2010s, some developers experimented with <keygen> for certificate-based login. Poor cross-browser support, low adoption, and security concerns led browsers and the HTML spec to drop the element entirely.

use-web-crypto-instead.js
// Modern replacement (simplified)
const keyPair = await crypto.subtle.generateKey(
  { name: "RSA-OAEP", modulusLength: 2048,
    publicExponent: new Uint8Array([1, 0, 1]), hash: "SHA-256" },
  true, ["encrypt", "decrypt"]
);

📝 Syntax (Historical)

Legacy HTML placed <keygen> inside a <form> with a required name attribute:

syntax.html
<form>
  <label for="keypair">Generate Key Pair:</label>
  <keygen name="keypair" id="keypair">
</form>

Syntax Rules

  • <keygen> was a void element — no closing tag or inner content.
  • It had to appear inside a <form> to submit the generated public key.
  • The name attribute was required for the key to appear in form data.
  • Modern HTML parsers treat the tag as unknown and do not generate key pairs.

⚡ Quick Reference

TopicLegacy (keygen)Modern replacement
Key generation<keygen name="key">crypto.subtle.generateKey()
Challenge stringchallenge attributeServer-issued nonce + Web Crypto
Key algorithmkeytype="rsa"Algorithm object in Web Crypto
Form bindingname on keygenJavaScript + fetch or hidden input
Transport securityNot built inHTTPS (TLS)
User loginObsolete experimentWebAuthn, OAuth, passkeys

⚖️ <keygen> vs Web Crypto API

Modern cryptography in the browser uses JavaScript APIs instead of HTML form controls:

Feature<keygen>Web Crypto API
StatusObsolete, removed from HTMLStandard, supported in modern browsers
Key typesRSA only (keytype="rsa")RSA, ECDSA, AES, and more
Browser supportRemoved from Chrome & FirefoxChrome, Firefox, Safari, Edge
ControlAutomatic on form submitFull programmatic control in JS
Security modelInconsistent, deprecatedActively maintained web platform API
migration.html
<!-- Legacy (do not use) -->
<form action="/register" method="post">
  <keygen name="keypair" challenge="server-nonce">
  <button type="submit">Register</button>
</form>

<!-- Modern: generate keys in JavaScript, send public key via fetch -->
<button type="button" id="register">Register</button>
<script>
  document.getElementById("register").addEventListener("click", async () => {
    const keys = await crypto.subtle.generateKey(/* ... */);
    // Export public key and POST to server over HTTPS
  });
</script>

🧰 Attributes (Historical)

Browsers that once supported <keygen> recognized these attributes:

name Required

Identified the generated public key in submitted form data.

name="keypair"
challenge Obsolete

Base64-encoded challenge string from the server to bind the key to a session.

challenge="randomstring"
keytype Obsolete

Key algorithm type. Only rsa was supported in practice.

keytype="rsa"
form Obsolete

Associated the control with a form by id when placed outside it.

form="my-form"
attributes.html
<keygen
  name="keypair"
  id="keypair"
  challenge="randomstring"
  keytype="rsa"
>

All keygen attributes are historical only. The entire element is obsolete and ignored by modern browsers.

Examples Gallery

Historical keygen patterns plus the modern Web Crypto approach. Legacy examples are for learning only—they will not work in current browsers.

👀 Live Preview

Modern secure forms use standard inputs and JavaScript APIs—not <keygen>:

⚠️ Use HTTPS + modern auth APIs instead of obsolete keygen.

Basic keygen with challenge

How <keygen> looked inside a form. For learning only—modern browsers ignore it.

⚠️ This tag is not supported in modern browsers.
legacy-keygen.html
<form>
  <label for="keypair">Generate Key Pair:</label>
  <keygen name="keypair" id="keypair" challenge="randomstring">
</form>

📚 Common Use Cases (Historical)

Developers once experimented with <keygen> for certificate-based login and client-side encryption. These use cases are now handled by Web Crypto, TLS, WebAuthn, and established authentication services.

Login Form with keygen

A historical pattern for generating a client key pair during registration or login.

login-keygen.html
<form action="/login" method="post">
  <label for="username">Username:</label>
  <input type="text" id="username" name="username">
  <label for="keypair">Key Pair:</label>
  <keygen name="keypair" id="keypair">
  <input type="submit" value="Login">
</form>

Form with Encryption Key

Another historical pattern that paired user data with a generated key on submit.

encrypt-keygen.html
<form action="/submit" method="post">
  <label for="data">Sensitive Data:</label>
  <input type="text" id="data" name="data">
  <label for="keypair">Encryption Key:</label>
  <keygen name="keypair" id="keypair">
  <input type="submit" value="Submit">
</form>

Modern Web Crypto Replacement

This is what developers use today. Generate keys in JavaScript and send the public key over HTTPS.

web-crypto.html
<button type="button" id="genKey">Generate Key Pair</button>
<p id="status"></p>
<script>
  document.getElementById("genKey").addEventListener("click", async () => {
    const keys = await crypto.subtle.generateKey(
      { name: "RSA-OAEP", modulusLength: 2048,
        publicExponent: new Uint8Array([1, 0, 1]), hash: "SHA-256" },
      true, ["encrypt", "decrypt"]
    );
    document.getElementById("status").textContent =
      "Key pair generated successfully.";
  });
</script>

Styling Secure Forms with CSS

Since <keygen> is obsolete, style the modern form controls you actually use for login and registration:

label Clear field labels
:focus Visible focus rings
autocomplete Password manager support
button Primary submit styling
secure-form.css
/* Modern login form styling */
form.auth-form {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  max-width: 360px;
}

form.auth-form input {
  padding: 0.5rem 0.75rem;
  border: 1px solid #cbd5e1;
  border-radius: 8px;
}

form.auth-form input:focus {
  outline: 2px solid #2563eb;
  outline-offset: 2px;
}

form.auth-form button {
  padding: 0.55rem 1rem;
  border: none;
  border-radius: 8px;
  background: #2563eb;
  color: #fff;
}

Live styled auth form

♿ Accessibility & Security

Modern authentication must work for all users and follow current security standards:

  • Use visible labels — every input needs a <label>; do not rely on placeholder text alone.
  • Support password managers — use correct autocomplete values on login fields.
  • Always use HTTPS — never transmit credentials or keys over plain HTTP.
  • Do not use obsolete keygen — it provided no accessibility benefits and is unsupported today.

🧠 How <keygen> Worked

1

Author added keygen to a form

Place keygen with a name inside form.

Markup
2

Browser generated RSA key pair

Supporting browsers created public and private keys when the form loaded or submitted.

Legacy only
3

Public key submitted with form

On submit, only the public key was sent; the private key stayed on the client.

Behavior
=

Today: use Web Crypto

Learn keygen for history. Generate keys with crypto.subtle and authenticate with modern APIs.

Browser Support

<keygen> is obsolete and removed from the HTML Living Standard. Chrome and Firefox dropped it years ago; modern browsers do not support it.

Obsolete · Use Web Crypto

Not supported in modern browsers

Chrome removed keygen in version 57, Firefox in version 56. Safari, Edge, and Opera never offered reliable support. Do not use this tag in new documents.

95% Legacy reference
Google Chrome Removed in v57 · Obsolete
Not supported
Mozilla Firefox Removed in v56 · Obsolete
Not supported
Apple Safari Never supported · Obsolete
Not supported
Microsoft Edge Not supported · Obsolete
Not supported
Internet Explorer Legacy partial · EOL
Legacy only
Opera Removed · Obsolete
Not supported

Modern replacements

Use these web platform APIs instead of keygen.

🔑
Web Crypto API crypto.subtle.generateKey() for key pairs
Replacement
🔒
WebAuthn / Passkeys Modern passwordless and strong authentication
Auth
<keygen> tag 95% legacy reference

Bottom line: Do not use <keygen> in new projects. Use the Web Crypto API, HTTPS, and modern authentication standards.

Conclusion

The <keygen> tag is a piece of web history—useful to recognize in old tutorials, but not for new sites. Beginners should learn the Web Crypto API, always deploy over HTTPS, and use established authentication patterns instead of obsolete HTML form controls.

💡 Best Practices

✅ Do

  • Use crypto.subtle for browser key generation
  • Serve all auth forms over HTTPS
  • Use autocomplete on login fields
  • Learn keygen only to read legacy HTML

❌ Don’t

  • Use <keygen> in any new HTML code
  • Assume keygen provides encryption by itself
  • Build login systems without modern auth standards
  • Transmit keys or passwords over plain HTTP

Key Takeaways

Knowledge Unlocked

Six truths every developer should know about <keygen>

Bookmark these before you ship — they’ll keep your security approach modern and safe.

6
Core concepts
🔑 02

Form Key Pairs

It generated RSA public/private keys on form submit.

Behavior
📝 03

name Required

The name attribute submitted the public key with the form.

Syntax
🚀 04

Use Web Crypto

crypto.subtle.generateKey() is the modern replacement.

Migration
🔒 05

HTTPS Always

Transport security requires TLS, not HTML tags.

Security
🚫 06

Browsers Dropped It

Chrome 57+ and Firefox 56+ do not support keygen.

Compatibility

❓ Frequently Asked Questions

It generated a public/private key pair inside a form. The public key was submitted to the server; the private key stayed on the client.
No. It was removed from the HTML Living Standard and is not supported in modern browsers.
The Web Crypto API for key generation, HTTPS for transport security, and WebAuthn for modern authentication.
name (required), challenge, keytype, autofocus, disabled, and form. All are obsolete.
No. Chrome removed it in version 57, Firefox in version 56. Current browsers ignore the tag.
No. Learn it to understand old HTML, but always use Web Crypto and modern auth for real projects.

Learn the Modern Way

Skip deprecated keygen. Practice Web Crypto key generation in the Try It editor.

Try Web Crypto →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

6 people found this page helpful