Skip to main content

API Authentication (2025)

This Help Center article is a temporary location for updated API 2.3 authentication documentation. Although most information available on the official authentication documentation page remains accurate, this article details updates implemented in June 2025.

Note for Users Before June 2025

If you used Stack Apps before the June 2025 release, you’ll notice a number of differences.

  • Added a more secure OAuth flow: authorization code w/PKCE (Proof Key for Code Exchange).
  • Updated some terminology to be in line with the OAuth 2.0 specification, including:
    • Client-side flow → Implicit grant
    • Explicit flow → Authorization code grant
    • Desktop Redirect URL → Non-Web Redirect URL
  • The new dashboard interface introduces the ability to create, name and rotate multiple API keys and client secrets for an application.

Stack Apps

The first step in accessing Stack Exchange API v2.3 is to register an application on Stack Apps. You'll use your Stack Apps registration to generate client secrets and API keys, configure OAuth, and more. To learn more about API version 2.3 and Stack Apps, see the documentation site.

The application registration process will provide you with a client_id value. This is a non-secret unique identifier that you'll use in all OAuth grant types. API key authentication does not use client_id. Registered applications will also be granted an increased throttle quota.

Access API v2.3

Stack Exchange API v2.3 provides two methods of authenticated access: API keys and OAuth access tokens. The type of authentication you choose depends on your use case, application type, and data access requirements. Use the table below to determine the best authorization type for your application.

OAuth Authorization Code OAuth Authorization Code
with PKCE (recommended)
OAuth Implicit API key
Suitable application and script types Server-side console or web application Server-side console or web application, SPA (single page application), native desktop application, mobile app SPA (single page application), native desktop application, mobile app All
Requires client secret Yes Only if confidential client No No
Level of security High Highest Low Low
Data access scope Public and private (as associated user) Public and private (as associated user) Public and private (as associated user) Public only
Read/write data as associated user Yes Yes Yes No

API key authentication

You can use an API key when you need simple read-only access. Because API keys have no user identity associated with them, they will return only public content. API keys are also required when using OAuth authentication.

To generate an API key, click Generate API Key on your application in Stack Apps. We recommend setting an expiration date on your API key. Be sure to store the newly generated key securely, such as in a password manager, as Stack Apps will not display it again.

OAuth authentication

You should use an OAuth access token when you need to read content that is restricted by user permissions (content that is not public), or when you need to perform write operations. You will still need to create an API key to make requests to the API.

Enable OAuth

To enable OAuth, click Manage OAuth in your application on Stack Apps. Select the grant types you will be using and enter your OAuth domain. It's important to enter a domain that you own since sensitive information will be transmitted and stored in server logs.

If your chosen authorization grant type requires a client secret, and your application is hosted on a server that you own, click Generate client secret to generate a new client secret. Be sure to store the secret securely, such as in a password manager, as Stack Apps will not display it again. Never use client secrets in an application that distributes the source code, such as SPAs (single-page applications) or native desktop applications.

Authorization Code grant

OAuth Authorization Code grant is intended for confidential clients, which are server-side applications that can securely store client secrets. If your application is a public client, use Authorization Code grant with PKCE instead.

NOTE: Though a StackApps application with this grant type doesn't explicitly mention PKCE, you can still use PKCE for additional CSRF (cross-site request forgery) protection. Instead of using the steps below, follow the steps for "Authorization Code grant with PKCE" and include a client_secret in step 5.

Follow these steps to generate an access token:

  1. Send a GET request to https://stackoverflow.com/oauth with these query parameters:
    • client_id The non-secret client identifier from the Stack Apps registration.
    • redirect_uri Where you'll be redirected after authorization. This URL must have the same domain as the one you entered in the “OAuth domain” section on Stack Apps.
    • state (optional, recommended) A random string you create that the authorization server returns for verification. This parameter provides CSRF (cross-site request forgery) protection.
    • scope (optional) See "Scope" in the official documentation.
  2. If you're not authenticated, Stack Exchange will prompt you to log in. You'll then authorize your app. Upon approval, Stack Exchange will redirect you to the URL provided in the redirect_uri query parameter.
    • The redirect will include the query parameter code. Copy this value for use in the next step.
    • If you provided the optional state query parameter, the redirect will include that as well.
      • NOTE: If the redirect's state value differs from what you provided in step 1, it's likely security was compromised. Terminate the process until you can locate and fix the problem.
  3. To exchange the authorization code for an access token, send a POST request to either https://stackoverflow/oauth/access_token (returns HTML form-encoded response), or https://stackoverflow/oauth/access_token/json (returns JSON-encoded response). Set the request content type to application/x-www-form-urlencoded, and include the following items in the request body:
    • client_id The non-secret client identifier from the Stack Apps registration (same as step 1).
    • redirect_uri The same redirect URL as step 1.
    • code The code value returned in step 2.
    • client_secret The client secret you generated when registering your application in Stack Apps.

The response will include the access token and, optionally, the expiration time in seconds. For example:

{ "access_token" : "value", "expires" : 86400 } 

You'll provide this OAuth access token with each API request. See "Authenticate API v2.3 requests" below.

Authorization Code grant with PKCE (recommended)

Authorization Code grant with PKCE (Proof Key for Code Exchange) adds additional safeguards to the basic OAuth Authorization Code grant. It improves security by ensuring that the application that starts the authentication process is the same one that finishes it. This is the method Stack Overflow recommends, and it's suitable for both public and confidential clients.

NOTE: Authorization Code with PKCE supports, but does not require, the client_secret parameter. If your application can securely store a client secret, we recommend adding one in step 5 below for optimum security.

Follow these steps to generate an access token:

  1. Generate a random code_verifier string. A code verifier is any random, cryptographically secure string with a length of 43 to 128 characters. It can include upper- and lower-case letters, numbers, and these symbols: "-", ".", "_", "~".
  2. Generate a code_challenge using the code verifier. The code challenge is the Base64URL-encoded SHA-256 hash of the code_verifier. Create the code challenge by hashing the code_verifier using SHA-256, then encode that hashed value using Base64URL.
  3. Send a GET request to https://stackoverflow.com/oauth with these query parameters:
    • client_id The non-secret client identifier from the Stack Apps registration.
    • redirect_uri Where you'll be redirected after authorization. This URL must have the same domain as the one you entered in the “OAuth domain” section on Stack Apps.
    • code_challenge The code challenge value you generated in step 2.
    • code_challenge_method This must be S256.
    • state (optional, recommended) A random string you create that the authorization server returns for verification. This parameter provides CSRF (cross-site request forgery) protection.
    • scope (optional) See "Scope" in the official documentation.
  4. If you're not authenticated, Stack Exchange will prompt you to log in. You'll then authorize your app. Upon approval, Stack Exchange will redirect you to the URL provided in the redirect_uri query parameter.
    • The redirect will include the query parameter code. Copy this value for use in the next step.
    • If you provided the optional state query parameter, the redirect will include that as well.
      • NOTE: If the redirect's state value differs from what you provided in step 1, it's likely security was compromised. Terminate the process until you can locate and fix the problem.
  5. To exchange the authorization code for an access token, send a POST request to either https://stackoverflow/oauth/access_token (returns HTML form-encoded response), or https://stackoverflow/oauth/access_token/json (returns JSON-encoded response). Set the request content type to application/x-www-form-urlencoded, and include the following items in the request body:
    • client_id The non-secret client identifier from the Stack Apps registration (same as step 3).
    • redirect_uri The same redirect URL as step 3.
    • code The code value returned in step 4.
    • code_verifier The string you created in step 1.
    • client_secret (optional, recommended if confidential client) The client secret you generated when registering your application in Stack Apps.

The response will include the access token and, optionally, the expiration time in seconds. For example:

{ "access_token" : "value", "expires" : 86400 } 

You'll provide this OAuth access token with each API request. See "Authenticate API v2.3 requests" below.

For a code example of Authorization Code with PKCE, see the "Code example" section below.

Implicit grant

Though inherently less secure than the other authentication methods, Stack Exchange still supports the OAuth Implicit grant type for legacy reasons.

NOTE: The OAuth 2.0 specification strongly recommends against using the Implicit grant type, given its inherent security risks. You should implement Authorization Code grant with PKCE if possible, using the Implicit grant type only as a last resort.

Follow these steps to generate an access token:

  1. Send a GET request to https://stackoverflow.com/oauth/dialog with these query parameters:
    • client_id The non-secret client identifier from the Stack Apps registration.
    • redirect_uri Where you'll be redirected after authorization. This URL must have the same domain as the one you entered in the “OAuth domain” section on Stack Apps.
    • scope (optional) See "Scope" in the official documentation.
  2. If you're not authenticated, Stack Exchange will prompt you to log in. You'll then authorize your app. Upon approval, Stack Exchange will redirect you to the URL provided in the redirect_uri query parameter.

The redirect will include the access token and, optionally, the expiration time in seconds in the fragment part of the URL. For example:

https://stackexchange.com/oauth/login_success#access_token={value}&expires=86400 

You'll provide this OAuth access token with each API request. See "Authenticate API v2.3 requests" below.

Authenticate API v2.3 requests

If you are using an API key, include the query parameter key with your API request. For example:

curl "https://api.stackexchange.com/2.3/questions?key={API_KEY}" 

If you are using OAuth access tokens, include the query parameters key and access_token to make an API request. For example:

curl "https://api.stackexchange.com/2.3/questions?key={API_KEY}&access_token={ACCESS_TOKEN}" 

Non-Web Redirect URL

If you don't own a domain, or are creating a non-web application, you can still use the OAuth Implicit grant type with www.stackexchange.com/oauth/login_success as your redirect URI. To do this, click Manage OAuth in Stack Apps. Enable Non-Web Redirect URL and Implicit. Follow the instructions above to configure OAuth implicit grant.

Code Example

Authorization Code grant with PKCE

ASP.NET Core MVC - Confidential Client/Server-side application

/// <summary> /// This is a simplified example of how to implement the PKCE flow in an /// ASP.NET Core MVC application. Please note that this example is not /// production-ready and should be used for educational purposes only. /// </summary> public class AuthController : Controller { private readonly IDataProtector _dataProtector; private const string AuthCodeEndpoint = "https://stackoverflow.com/oauth"; private const string AccessTokenEndpoint = "https://stackoverflow.com/oauth/access_token/json"; private const string CodeVerifierCookieName = "code_verifier"; private const string CodeChallengeMethod = "S256"; // Update these values with your own. // These have been embedded for simplicity, but should be passed through configuration. private readonly string ClientId = "your_client_id"; private readonly string ClientSecret = "your_client_secret"; private readonly string RedirectUri = "https://localhost/auth/callback"; private record AccessTokenJsonResponse(string access_token, int expires_in); public AuthController(IDataProtectionProvider dataProtectorProvider) { _dataProtector = dataProtectorProvider.CreateProtector(nameof(AuthController)); } [HttpGet] [Route("auth/start")] public IActionResult GetAuthorizationCode() { var codeVerifier = GenerateCodeVerifier(); var codeChallenge = GenerateCodeChallenge(codeVerifier); var query = HttpUtility.ParseQueryString(string.Empty); query["client_id"] = ClientId; query["redirect_uri"] = RedirectUri; query["code_challenge"] = codeChallenge; query["code_challenge_method"] = CodeChallengeMethod; Response.Cookies.Append( CodeVerifierCookieName, _dataProtector.Protect(codeVerifier), options: new CookieOptions { Expires = DateTimeOffset.Now.AddMinutes(15), HttpOnly = true } ); return Redirect($"{AuthCodeEndpoint}?{query.ToString()}"); } [HttpGet] [Route("auth/callback")] public async Task<IActionResult> GetAccessToken(string code) { var codeVerifier = _dataProtector.Unprotect(Request.Cookies[CodeVerifierCookieName]); var httpClient = new HttpClient(); var request = new HttpRequestMessage(HttpMethod.Post, AccessTokenEndpoint); request.Content = new FormUrlEncodedContent( [ new KeyValuePair<string, string>("client_id", ClientId), new KeyValuePair<string, string>("redirect_uri", RedirectUri), new KeyValuePair<string, string>("code", code), new KeyValuePair<string, string>("code_verifier", codeVerifier), // Since this is a confidential client, we can use a client_secret new KeyValuePair<string, string>("client_secret", ClientSecret) ]); // You must include the User-Agent header to use the Stack Exchange API. request.Headers.Add("User-Agent", "My App"); var response = await httpClient.SendAsync(request); var content = await response.Content.ReadFromJsonAsync<AccessTokenJsonResponse>(); var accessToken = content?.access_token; Response.Cookies.Delete(CodeVerifierCookieName); return Ok(); } string GenerateCodeVerifier() { var bytes = new byte[32]; using (var rng = RandomNumberGenerator.Create()) { rng.GetBytes(bytes); } return Base64UrlEncoder.Encode(bytes); } string GenerateCodeChallenge(string codeVerifier) { using (var sha256 = SHA256.Create()) { var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier)); return Base64UrlEncoder.Encode(challengeBytes); } } }