---
title: Customize the One-Time Password (OTP)
description: Configure OTP by changing the format or by modifying the token duration
sidebar:
  order: 40
---

## Change the OTP format

By default, the generated OTP is 6 digits long and is numbers only. You can change this to be any length you like and have any character set by providing the `getCustomUserInputCode` function.

<CodeGroup group="backend-language">
<Tab title="Node.js" value="nodejs">
```tsx
import SuperTokens from "supertokens-node";
import Passwordless from "supertokens-node/recipe/passwordless";

SuperTokens.init({
  appInfo: {
    apiDomain: "...",
    appName: "...",
    websiteDomain: "...",
  },
  recipeList: [
    Passwordless.init({
      contactMethod: "EMAIL", // This example will work with any contactMethod
      // This example works with the "USER_INPUT_CODE_AND_MAGIC_LINK" and "USER_INPUT_CODE" flows.
      flowType: "USER_INPUT_CODE_AND_MAGIC_LINK",

      getCustomUserInputCode: async (userCtx) => {
        // TODO:
        return "123abcd";
      },
    }),
  ],
});
```
</Tab>
<Tab title="Go" value="go">
```go
import (
	"github.com/supertokens/supertokens-golang/recipe/passwordless"
	"github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels"
	"github.com/supertokens/supertokens-golang/supertokens"
)

func main() {
	supertokens.Init(supertokens.TypeInput{
		RecipeList: []supertokens.Recipe{
			passwordless.Init(plessmodels.TypeInput{
				GetCustomUserInputCode: func(tenantId string, userContext supertokens.UserContext) (string, error) {
					// TODO:
					return "123abcd", nil
				},
			}),
		},
	})
}
```
</Tab>
<Tab title="Python" value="python">
```python check=false reason="This example omits surrounding application and SuperTokens configuration."
from supertokens_python import init, InputAppInfo
from supertokens_python.recipe import passwordless
from typing import Dict, Any

async def get_custom_user_input_code(tenant_id: str, user_context: Dict[str, Any]):
    return "123abcd" # TODO

init(
    app_info=InputAppInfo(api_domain="...", app_name="...", website_domain="..."),
    framework='...',
    recipe_list=[
        passwordless.init(
            contact_config=...,
            flow_type="...",
            get_custom_user_input_code=get_custom_user_input_code
        )
    ]
)
```
</Tab>
</CodeGroup>

---

## Limit OTP retries

You can change how many times a user can attempt to enter an OTP before they have to enter their email / phone number again (thereby force generating a new OTP). By default, this value is `5` attempts, and you can modify it by changing the `passwordless_max_code_input_attempts` core configuration:

<DependentContent passive group="core-deployment">
<ContentOption title="With Saas" value="saas">
- Open the [SaaS Dashboard](https://supertokens.com/dashboard), select the relevant **Managed** deployment, and open **Configuration**.
- In the **Passwordless** configuration card, change the value. Configuration changes are saved automatically.
</ContentOption>
</DependentContent>

<CodeGroup group="core-deployment">
<Tab title="With Docker" value="with-docker">
```bash
docker run \
  -p 3567:3567 \
  -e PASSWORDLESS_MAX_CODE_INPUT_ATTEMPTS=3 \
  -d supertokens/supertokens-<db name>
```
</Tab>
<Tab title="Without Docker" value="without-docker">
```yaml
# You need to add the following to the config.yaml file.
# The file path can be found by running the "supertokens --help" command

passwordless_max_code_input_attempts: 3
```
</Tab>
<Tab title="With Saas" value="saas">
```yaml
passwordless_max_code_input_attempts: 3
```
</Tab>
</CodeGroup>

---

## Change the OTP lifetime


You can change how long a user can use an OTP or a Magic Link to log in by changing the `passwordless_code_lifetime` core configuration value. This value defaults to `900000` milliseconds (15 minutes).

:::warning[Each new OTP / magic link generated, either by opening a new browser or by clicking on the "Resend" button, has a lifetime per the `passwordless_code_lifetime` setting.]

:::

<DependentContent passive group="core-deployment">
<ContentOption title="With Saas" value="saas">
- Open the [SaaS Dashboard](https://supertokens.com/dashboard), select the relevant **Managed** deployment, and open **Configuration**.
- In the **Passwordless** configuration card, change the value. Configuration changes are saved automatically.
</ContentOption>
</DependentContent>

<CodeGroup group="core-deployment">
<Tab title="With Docker" value="with-docker">
```bash
docker run \
  -p 3567:3567 \
  -e PASSWORDLESS_CODE_LIFETIME=60000 \
  -d supertokens/supertokens-<db name>
```
</Tab>
<Tab title="Without Docker" value="without-docker">
```yaml
# You need to add the following to the config.yaml file.
# The file path can be found by running the "supertokens --help" command

passwordless_code_lifetime: 60000
```
</Tab>
<Tab title="With Saas" value="saas">
```yaml
passwordless_code_lifetime: 60000
```
</Tab>
</CodeGroup>

---

## See also

<CardGroup cols={3}>
  <Card title="Customize the magic link" href="/authentication/passwordless/customize-the-magic-link" />
  <Card title="Hooks and overrides" href="/authentication/passwordless/hooks-and-overrides" />
  <Card title="Email and SMS behavior" href="/authentication/passwordless/configure-email-and-sms-behavior" />
  <Card title="Invite link sign up" href="/authentication/passwordless/invite-link-flow" />
  <Card title="Allow list sign up" href="/authentication/passwordless/allow-list-flow" />
  <Card title="Email Delivery" href="/platform-configuration/email-delivery" />
  <Card title="SMS Delivery" href="/platform-configuration/sms-delivery" />
</CardGroup>
