WordPress salt generator

All eight WordPress authentication keys and salts at once, with an explanation of what each one does.

G
More options
up to 10,000

Constraints

The official endpoint, and what this page adds

https://api.wordpress.org/secret-key/1.1/salt/ is the canonical source for these values. It is run by WordPress, it is what the installer and every tutorial point at, and if you want a ready-made block of PHP to paste, you should use it. Nothing here changes that.

What it returns is eight define() lines and nothing else. It does not say what the eight constants are for, which of them matters on an HTTPS site, why they come in pairs, or what will happen to your logged-in users when you replace them. That is the gap this page fills, along with output in .env form for installations that keep configuration outside wp-config.php.

The values above are generated in your browser and never transmitted. That is a genuine difference from any endpoint, official or otherwise: a value fetched over HTTP existed on someone else's machine first and was written into at least one access log on the way to you.

The eight constants, and what each pair holds together

They are four keys and four salts, and they work in pairs. WordPress combines the key and salt for a given scheme in wp_salt(), and the result becomes the HMAC key inside wp_hash(). Each pair protects a different cookie or token, which is why replacing one pair has a different effect from replacing another.

The distinction between the first two pairs is the one people miss. AUTH is used for the authentication cookie sent over plain HTTP; SECURE_AUTH is used for the equivalent cookie when the admin area is served over HTTPS. On a site that is HTTPS throughout, which is every site now, SECURE_AUTH is the pair doing the work.

What each pair covers
PairSchemeProtectsEffect of changing it
AUTH_KEY / AUTH_SALTauthThe wordpress_ authentication cookie, used when the admin is served over plain HTTPInvalidates that cookie for every user
SECURE_AUTH_KEY / SECURE_AUTH_SALTsecure_authThe wordpress_sec_ cookie, the HTTPS equivalent and the one in use on a modern siteSigns out every user of an HTTPS site
LOGGED_IN_KEY / LOGGED_IN_SALTlogged_inThe wordpress_logged_in_ cookie, which only asserts that someone is signed in and drives the front-end toolbarDrops the signed-in state on the front end
NONCE_KEY / NONCE_SALTnonceValues from wp_create_nonce, used in admin forms and action URLsInvalidates every nonce on an already-rendered page, so an open form fails once and works after a reload

If a constant is missing from wp-config.php, WordPress generates one and stores it in the options table. It then lives in your database, which means it is in every database dump and every backup you have ever taken. Defining all eight in the config file is what keeps them out of there.

What changing them does, and what it does not

Replacing all eight signs out every logged-in user immediately, including the person who made the change, and cancels every remember-me session. Any nonce on a page a user currently has open stops verifying, so a form submitted at that moment fails with a security check message and succeeds after a reload. That is the whole blast radius, and it recovers by itself.

What it does not do is touch passwords. WordPress hashes passwords separately, and no user password is derived from these constants. Rotating salts is therefore not a remedy for a leaked user table, and telling people otherwise is a common piece of bad advice. It also does not change any content, plugin setting or database row beyond the authentication cookies it invalidates.

Worth doing after any of the following: a compromise or suspected compromise, handing a site over to a new owner, a developer or agency with wp-config.php access leaving, or restoring a production database into an environment where the old sessions should not be honoured. Rotating on a schedule for its own sake achieves nothing except signing everyone out on a schedule.

Length, characters and where the block goes

The official endpoint returns 64-character values, and the default here matches it. WordPress does not require any particular length, because the constants are used as HMAC key material and HMAC accepts a key of any size. Sixty-four characters over a 74-symbol alphabet is 397.41 bits per value, which is more than enough by an enormous margin and costs nothing.

The characters do matter, for a PHP reason rather than a cryptographic one. Put the values in single-quoted strings. Inside a double-quoted PHP string a dollar sign begins a variable and a backslash begins an escape sequence, and either will silently change the value your site actually uses. The default symbol set here is !#$%*+-=?@^_ , which contains neither a backslash nor a single quote, so the block below needs no escaping at all.

Placement is simple but unforgiving: the define() calls have to appear before the require_once for wp-settings.php at the bottom of wp-config.php, because that line is where WordPress reads them. The standard block sits in the middle of the file for exactly that reason. If you manage configuration through environment variables, define the constants from the environment in the same position rather than trying to set them later.

Doing this in your own code

wp-config.php
/**#@+
 * Authentication unique keys and salts.
 * These must be defined before the require_once for wp-settings.php at the
 * bottom of this file, which is where WordPress reads them.
 */
define( 'AUTH_KEY',         'value 1' );
define( 'SECURE_AUTH_KEY',  'value 2' );
define( 'LOGGED_IN_KEY',    'value 3' );
define( 'NONCE_KEY',        'value 4' );
define( 'AUTH_SALT',        'value 5' );
define( 'SECURE_AUTH_SALT', 'value 6' );
define( 'LOGGED_IN_SALT',   'value 7' );
define( 'NONCE_SALT',       'value 8' );
/**#@-*/

Single quotes, always. In a double-quoted PHP string a $ starts a variable and a backslash starts an escape, and salts routinely contain both.

wp-config.php with a .env file
// With a loader such as vlucas/phpdotenv the constants are still what
// WordPress reads. The .env file only keeps them out of the repository.
foreach ([
    'AUTH_KEY', 'SECURE_AUTH_KEY', 'LOGGED_IN_KEY', 'NONCE_KEY',
    'AUTH_SALT', 'SECURE_AUTH_SALT', 'LOGGED_IN_SALT', 'NONCE_SALT',
] as $constant) {
    define( $constant, $_ENV[$constant] );
}
WP-CLI
# Replace all eight in place. Every logged-in user is signed out,
# including whoever runs this.
wp config shuffle-salts

# Read one back.
wp config get AUTH_KEY
The official endpoint
# Returns eight ready-made define() lines and nothing else.
curl https://api.wordpress.org/secret-key/1.1/salt/

This is the canonical source. If the PHP block is all you need, use it.

Questions

Should I use the official WordPress salt endpoint instead?

If you want a ready-made PHP block, yes. It is the canonical source and there is nothing wrong with it. The reasons to use this page are that the values here never travel over a network, that you get eight of them in .env form as well as PHP, and that this page tells you what each of the eight constants does.

What happens when I change the salts?

Every logged-in user is signed out, including you, and nonces on already-rendered pages stop verifying so one form submission may fail before a reload fixes it. Passwords, content and settings are untouched. Nothing has to be repaired afterwards.

Do I need all eight, or only the four keys?

Define all eight. The keys and salts are combined in pairs to derive the HMAC key for each scheme, and omitting a salt does not disable it: WordPress generates one and stores it in the database instead, which is precisely the outcome the config file exists to avoid.

Will changing the salts fix a hacked site?

It ends every existing session, which is a useful part of the response, but it is not a fix on its own. If an attacker has file access or a database account they can create a new session at will. Rotating salts belongs alongside a password reset, a file integrity check and closing whatever the entry point was.

How long should the values be?

Sixty-four characters, matching the official endpoint. WordPress imposes no requirement, since they are used as HMAC key material, and anything above roughly 32 random characters is already beyond reach. There is no reason to depart from the familiar length.

Related generators