---
title: Create a Token Account
description:
  Create token accounts and associated token accounts for a specific mint and
  owner.
url: /docs/tokens/basics/create-token-account
type: tutorial
prerequisites:
  - /docs/tokens/basics
  - /docs/tokens/basics/create-mint
related:
  - /docs/tokens/basics/mint-tokens
  - /docs/tokens/basics/transfer-tokens
  - /docs/tokens/basics/close-account
  - /docs/tokens/basics/sync-native
---

## What Is a Token Account

A token account stores tokens for one mint and one token account owner on
Solana.

```rust title="Token Account Type"
/// Account data.
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Account {
    /// The mint associated with this account
    pub mint: Pubkey,
    /// The owner of this account.
    pub owner: Pubkey,
    /// The amount of tokens this account holds.
    pub amount: u64,
    /// If `delegate` is `Some` then `delegated_amount` represents
    /// the amount authorized by the delegate
    pub delegate: COption<Pubkey>,
    /// The account's state
    pub state: AccountState,
    /// If `is_native.is_some`, this is a native token, and the value logs the
    /// rent-exempt reserve. An Account is required to be rent-exempt, so
    /// the value is used by the Processor to ensure that wrapped SOL
    /// accounts do not drop below this threshold.
    pub is_native: COption<u64>,
    /// The amount delegated
    pub delegated_amount: u64,
    /// Optional authority to close the account.
    pub close_authority: COption<Pubkey>,
}
```

Here, _rs`owner`_ means the authority that can transfer, burn, or delegate
tokens from the token account. The account's program owner is still the Token
Program or Token Extension Program.

Each token account is tied to exactly one mint, which means the token account
can hold units of only one token, the token identified by the token account's
_rs`mint`_ field.

## What Is an Associated Token Account

An associated token account (ATA) is the default token account for a wallet and
mint. The
[Associated Token Program](https://github.com/solana-program/associated-token-account/tree/main/program/src)
derives the ATA address from the wallet address, token program address, and mint
address.

Only token accounts created by the Associated Token Program are called
associated token accounts.

The Associated Token Program is a way to create a token account at a standard,
deterministic address. The resulting account is still a token account owned by
the Token Program or Token Extension Program, not by the Associated Token
Program.

The Associated Token Program derives the ATA address as shown in
[address.rs](https://github.com/solana-program/associated-token-account/blob/program%40v8.0.0/interface/src/address.rs#L56-L70):

```rust title="Associated Token Account Address Derivation"
pub fn get_associated_token_address_and_bump_seed_internal(
    wallet_address: &Pubkey,
    token_mint_address: &Pubkey,
    program_id: &Pubkey,
    token_program_id: &Pubkey,
) -> (Pubkey, u8) {
    Pubkey::find_program_address(
        &[
            &wallet_address.to_bytes(), // Owner's public key
            &token_program_id.to_bytes(), // Token Program or Token Extension Program
            &token_mint_address.to_bytes(), // Token mint address
        ],
        program_id, // Associated Token Program ID
    )
}
```

For any wallet, token program, and mint combination, there is exactly one ATA
address. The Associated Token Program creates a standard token account at that
address, and the resulting account still uses the _rs`Account`_ type defined by
the Token Program or Token Extension Program.

## How to Create an Associated Token Account

Creating an associated token account uses the Associated Token Program's
_rs`Create`_ or _rs`CreateIdempotent`_ instruction. The Associated Token Program
derives the ATA address, creates the account at the ATA address, and initializes
the account as a token account owned by the Token Program or Token Extension
Program.

<Callout type="info" title="Recommended">
  For most applications, create token accounts through the Associated Token
  Program instead of creating them by directly calling the System Program and
  Token Program instructions. An associated token account uses a deterministic
  address derived from the owner, token program, and mint, which makes the
  default token account for a given mint easier for wallets and applications to
  find.
</Callout>

### Source Reference

| Item                                          | Description                                                                                                                                                                                                                                                    | Source                                                                                                                          |
| --------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| _rs`Create`_                                  | Creates an associated token account at the derived ATA address.                                                                                                                                                                                                | [Source](https://github.com/solana-program/associated-token-account/blob/program%40v8.0.0/interface/src/instruction.rs#L20-L29) |
| _rs`CreateIdempotent`_                        | Creates the associated token account, but still succeeds if that ATA already exists for the same owner and mint.                                                                                                                                               | [Source](https://github.com/solana-program/associated-token-account/blob/program%40v8.0.0/interface/src/instruction.rs#L30-L40) |
| _rs`process_create_associated_token_account`_ | Derives the ATA address and uses _rs`create_pda_account`_ plus CPIs to the selected token program to initialize the token account. When the selected program is the Token Extension Program, the ATA processor also initializes the immutable owner extension. | [Source](https://github.com/solana-program/associated-token-account/blob/program%40v8.0.0/program/src/processor.rs#L64-L161)    |
| _rs`create_pda_account`_                      | Helper used by _rs`process_create_associated_token_account`_ to create the PDA account by CPI into the System Program.                                                                                                                                         | [Source](https://github.com/solana-program/associated-token-account/blob/program%40v8.0.0/program/src/tools/account.rs#L14-L70) |

### Typescript

The `Kit` examples below show the recommended approach using `@solana/kit`.
Legacy examples using `@solana/web3.js` are included for reference.

#### Kit

<CodeTabs storage="token-ts-kit" flags="r">

```ts !! title="Plugin"
import { createClient, generateKeyPairSigner, lamports } from "@solana/kit";
import { solanaRpc, rpcAirdrop } from "@solana/kit-plugin-rpc";
import { generatedPayer, airdropPayer } from "@solana/kit-plugin-signer";
import {
  associatedTokenProgram,
  findAssociatedTokenPda,
  tokenProgram,
  TOKEN_PROGRAM_ADDRESS
} from "@solana-program/token";

const client = await createClient()
  .use(generatedPayer())
  .use(
    solanaRpc({
      rpcUrl: "http://localhost:8899",
      rpcSubscriptionsUrl: "ws://localhost:8900"
    })
  )
  .use(rpcAirdrop())
  .use(airdropPayer(lamports(1_000_000_000n)))
  // !mark[/\.use\(tokenProgram\(\)\)/]
  .use(tokenProgram())
  // !mark[/\.use\(associatedTokenProgram\(\)\)/]
  .use(associatedTokenProgram());

// !collapse(1:11) collapsed
// Setup: Create a mint for this example.
const mint = await generateKeyPairSigner();

await client.token.instructions
  .createMint({
    newMint: mint,
    decimals: 2,
    mintAuthority: client.payer.address,
    freezeAuthority: client.payer.address
  })
  .sendTransaction();

const result = await client.associatedToken.instructions
  // !mark(1:5)
  .createAssociatedToken({
    payer: client.payer, // Account funding account creation.
    mint: mint.address, // Mint for the token this account holds.
    owner: client.payer.address // Account that owns the token account.
  })
  .sendTransaction();

const [associatedTokenAddress] = await findAssociatedTokenPda({
  mint: mint.address,
  owner: client.payer.address,
  tokenProgram: TOKEN_PROGRAM_ADDRESS
});

const tokenAccountData = await client.token.accounts.token.fetch(
  associatedTokenAddress
);

console.log("Mint Address:", mint.address);
console.log("\nAssociated Token Account Address:", associatedTokenAddress);
console.log("Associated Token Account:", tokenAccountData.data);
console.log("\nTransaction Signature:", result.context.signature);
```

```ts !! title="Instructions"
import { createClient, generateKeyPairSigner, lamports } from "@solana/kit";
import { solanaRpc, rpcAirdrop } from "@solana/kit-plugin-rpc";
import { generatedPayer, airdropPayer } from "@solana/kit-plugin-signer";
import { getCreateAccountInstruction } from "@solana-program/system";
import {
  fetchToken,
  findAssociatedTokenPda,
  getCreateAssociatedTokenInstructionAsync,
  getInitializeMintInstruction,
  getMintSize,
  TOKEN_PROGRAM_ADDRESS
} from "@solana-program/token";

const client = await createClient()
  .use(generatedPayer())
  .use(
    solanaRpc({
      rpcUrl: "http://localhost:8899",
      rpcSubscriptionsUrl: "ws://localhost:8900"
    })
  )
  .use(rpcAirdrop())
  .use(airdropPayer(lamports(1_000_000_000n)));

// !collapse(1:27) collapsed
// Setup: Create a mint for this example.
const mint = await generateKeyPairSigner();

const space = BigInt(getMintSize());
const rent = await client.rpc.getMinimumBalanceForRentExemption(space).send();

await client.sendTransaction([
  getCreateAccountInstruction({
    payer: client.payer,
    newAccount: mint,
    lamports: rent,
    space,
    programAddress: TOKEN_PROGRAM_ADDRESS
  }),
  getInitializeMintInstruction({
    mint: mint.address,
    decimals: 2,
    mintAuthority: client.payer.address,
    freezeAuthority: client.payer.address
  })
]);

const [associatedTokenAddress] = await findAssociatedTokenPda({
  mint: mint.address,
  owner: client.payer.address,
  tokenProgram: TOKEN_PROGRAM_ADDRESS
});

const result = await client.sendTransaction([
  // !mark(1:5)
  await getCreateAssociatedTokenInstructionAsync({
    payer: client.payer, // Account funding account creation.
    mint: mint.address, // Mint for the token this account holds.
    owner: client.payer.address // Account that owns the token account.
  })
]);

const tokenAccountData = await fetchToken(client.rpc, associatedTokenAddress);

console.log("Mint Address:", mint.address);
console.log("\nAssociated Token Account Address:", associatedTokenAddress);
console.log("Associated Token Account:", tokenAccountData.data);
console.log("\nTransaction Signature:", result.context.signature);
```

</CodeTabs>
#### Web3.js

<CodeTabs storage="token-ts-legacy" flags="r">

```ts !! title="Helper Function"
import { Connection, Keypair, LAMPORTS_PER_SOL } from "@solana/web3.js";
import {
  createAssociatedTokenAccount,
  createMint,
  getAccount,
  TOKEN_PROGRAM_ID
} from "@solana/spl-token";

// !collapse(1:28) collapsed
// Setup: create a mint before creating the associated token account.
const connection = new Connection("http://localhost:8899", "confirmed");
const latestBlockhash = await connection.getLatestBlockhash();

const feePayer = Keypair.generate();

const airdropSignature = await connection.requestAirdrop(
  feePayer.publicKey,
  LAMPORTS_PER_SOL
);
await connection.confirmTransaction({
  blockhash: latestBlockhash.blockhash,
  lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
  signature: airdropSignature
});

const mintPubkey = await createMint(
  connection,
  feePayer,
  feePayer.publicKey,
  feePayer.publicKey,
  2,
  Keypair.generate(),
  {
    commitment: "confirmed"
  },
  TOKEN_PROGRAM_ID
);

// !mark(1:10)
const associatedTokenAccount = await createAssociatedTokenAccount(
  connection, // Connection to the local validator.
  feePayer, // Account funding account creation.
  mintPubkey, // Mint for the token this account holds.
  feePayer.publicKey, // Account that owns the token account.
  {
    commitment: "confirmed" // Confirmation options for the transaction.
  },
  TOKEN_PROGRAM_ID // Token program to invoke.
);

const tokenAccountData = await getAccount(
  connection,
  associatedTokenAccount,
  "confirmed",
  TOKEN_PROGRAM_ID
);

console.log("Mint Address:", mintPubkey.toBase58());
console.log(
  "\nAssociated Token Account Address:",
  associatedTokenAccount.toBase58()
);
console.log("Associated Token Account:", tokenAccountData);
```

```ts !! title="Instructions"
import {
  Connection,
  Keypair,
  sendAndConfirmTransaction,
  SystemProgram,
  Transaction,
  LAMPORTS_PER_SOL
} from "@solana/web3.js";
import {
  ASSOCIATED_TOKEN_PROGRAM_ID,
  createAssociatedTokenAccountInstruction,
  createInitializeMintInstruction,
  getAccount,
  getAssociatedTokenAddressSync,
  getMinimumBalanceForRentExemptMint,
  MINT_SIZE,
  TOKEN_PROGRAM_ID
} from "@solana/spl-token";

// !collapse(1:50) collapsed
// Setup: create a mint before creating the associated token account.
const connection = new Connection("http://localhost:8899", "confirmed");
const latestBlockhash = await connection.getLatestBlockhash();

const feePayer = Keypair.generate();

const airdropSignature = await connection.requestAirdrop(
  feePayer.publicKey,
  LAMPORTS_PER_SOL
);
await connection.confirmTransaction({
  blockhash: latestBlockhash.blockhash,
  lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
  signature: airdropSignature
});

const mint = Keypair.generate();
const mintRent = await getMinimumBalanceForRentExemptMint(connection);
await sendAndConfirmTransaction(
  connection,
  new Transaction({
    feePayer: feePayer.publicKey,
    blockhash: latestBlockhash.blockhash,
    lastValidBlockHeight: latestBlockhash.lastValidBlockHeight
  }).add(
    SystemProgram.createAccount({
      fromPubkey: feePayer.publicKey,
      newAccountPubkey: mint.publicKey,
      space: MINT_SIZE,
      lamports: mintRent,
      programId: TOKEN_PROGRAM_ID
    }),
    createInitializeMintInstruction(
      mint.publicKey,
      2,
      feePayer.publicKey,
      feePayer.publicKey,
      TOKEN_PROGRAM_ID
    )
  ),
  [feePayer, mint]
);

const associatedTokenAccount = getAssociatedTokenAddressSync(
  mint.publicKey,
  feePayer.publicKey,
  false, // allowOwnerOffCurve
  TOKEN_PROGRAM_ID,
  ASSOCIATED_TOKEN_PROGRAM_ID
);

const result = await sendAndConfirmTransaction(
  connection,
  new Transaction({
    feePayer: feePayer.publicKey,
    blockhash: latestBlockhash.blockhash,
    lastValidBlockHeight: latestBlockhash.lastValidBlockHeight
  }).add(
    // !mark(1:8)
    createAssociatedTokenAccountInstruction(
      feePayer.publicKey, // Account funding account creation.
      associatedTokenAccount, // Associated token account to create.
      feePayer.publicKey, // Account that owns the token account.
      mint.publicKey, // Mint for the token this account holds.
      TOKEN_PROGRAM_ID,
      ASSOCIATED_TOKEN_PROGRAM_ID
    )
  ),
  [feePayer]
);

const tokenAccountData = await getAccount(
  connection,
  associatedTokenAccount,
  "confirmed",
  TOKEN_PROGRAM_ID
);

console.log("Mint Address:", mint.publicKey.toBase58());
console.log(
  "\nAssociated Token Account Address:",
  associatedTokenAccount.toBase58()
);
console.log("Associated Token Account:", tokenAccountData);
console.log("\nTransaction Signature:", result);
```

</CodeTabs>

### Rust

<CodeTabs storage="token-rs" flags="r">

```rust !! title="Rust"
use anyhow::Result;
use solana_client::nonblocking::rpc_client::RpcClient;
use solana_commitment_config::CommitmentConfig;
use solana_sdk::{
    program_pack::Pack,
    signature::{Keypair, Signer},
    transaction::Transaction,
};
use solana_system_interface::instruction::create_account;
use spl_associated_token_account_interface::{
    address::get_associated_token_address, instruction::create_associated_token_account,
};
use spl_token_interface::{
    id as token_program_id,
    instruction::initialize_mint,
    state::{Account, Mint},
};

#[tokio::main]
async fn main() -> Result<()> {
    let client = RpcClient::new_with_commitment(
        String::from("http://localhost:8899"),
        CommitmentConfig::confirmed(),
    );

    // !collapse(1:41) collapsed
    // Setup: create a mint before creating the associated token account.
    let fee_payer = Keypair::new();

    let airdrop_signature = client
        .request_airdrop(&fee_payer.pubkey(), 1_000_000_000)
        .await?;
    loop {
        let confirmed = client.confirm_transaction(&airdrop_signature).await?;
        if confirmed {
            break;
        }
    }

    let mint = Keypair::new();
    let mint_rent = client
        .get_minimum_balance_for_rent_exemption(Mint::LEN)
        .await?;

    let latest_blockhash = client.get_latest_blockhash().await?;
    let setup_transaction = Transaction::new_signed_with_payer(
        &[
            create_account(
                &fee_payer.pubkey(),
                &mint.pubkey(),
                mint_rent,
                Mint::LEN as u64,
                &token_program_id(),
            ),
            initialize_mint(
                &token_program_id(),
                &mint.pubkey(),
                &fee_payer.pubkey(),
                Some(&fee_payer.pubkey()),
                2,
            )?,
        ],
        Some(&fee_payer.pubkey()),
        &[&fee_payer, &mint],
        latest_blockhash,
    );
    client.send_and_confirm_transaction(&setup_transaction).await?;

    let transaction = Transaction::new_signed_with_payer(
        &[
            // !mark(1:6)
            create_associated_token_account(
                &fee_payer.pubkey(), // Account funding account creation.
                &fee_payer.pubkey(), // Account that owns the token account.
                &mint.pubkey(), // Mint for the token this account holds.
                &token_program_id(), // Token program that owns the account.
            ),
        ],
        Some(&fee_payer.pubkey()),
        &[&fee_payer],
        latest_blockhash,
    );

    let transaction_signature = client.send_and_confirm_transaction(&transaction).await?;
    let associated_token_account = get_associated_token_address(&fee_payer.pubkey(), &mint.pubkey());
    let token_account = client.get_account(&associated_token_account).await?;
    let token_data = Account::unpack(&token_account.data)?;

    println!("Mint Address: {}", mint.pubkey());
    println!(
        "\nAssociated Token Account Address: {}",
        associated_token_account
    );
    println!("Associated Token Account: {:#?}", token_data);
    println!("\nTransaction Signature: {}", transaction_signature);

    Ok(())
}
```

</CodeTabs>

### Python

<CodeTabs flags="r">

```py !! title="Python"
#!/usr/bin/env python3

import asyncio
import json
from solana.rpc.async_api import AsyncClient
from solders.keypair import Keypair
from solders.message import Message
from solders.pubkey import Pubkey
from solders.system_program import create_account, CreateAccountParams
from solders.transaction import Transaction
from spl.token.async_client import AsyncToken
from spl.token.instructions import (
    create_associated_token_account,
    get_associated_token_address,
    initialize_mint,
    InitializeMintParams,
)
from spl.token.constants import MINT_LEN, TOKEN_PROGRAM_ID

async def main():
    rpc = AsyncClient("http://localhost:8899")

    fee_payer = Keypair()
    owner = Keypair()

    async with rpc:
        # !collapse(1:18) collapsed
        # Setup: create and initialize a mint before creating the ATA.
        airdrop_signature = (await rpc.request_airdrop(fee_payer.pubkey(), 1_000_000_000)).value
        await rpc.confirm_transaction(airdrop_signature)
        mint = Keypair()
        associated_token_account = get_associated_token_address(owner.pubkey(), mint.pubkey())
        mint_rent = (await rpc.get_minimum_balance_for_rent_exemption(MINT_LEN)).value
        setup_instructions = [
            create_account(CreateAccountParams(from_pubkey=fee_payer.pubkey(), to_pubkey=mint.pubkey(), lamports=mint_rent, space=MINT_LEN, owner=TOKEN_PROGRAM_ID)),
            initialize_mint(InitializeMintParams(decimals=2, program_id=TOKEN_PROGRAM_ID, mint=mint.pubkey(), mint_authority=fee_payer.pubkey(), freeze_authority=fee_payer.pubkey())),
        ]
        setup_blockhash = await rpc.get_latest_blockhash()
        setup_transaction = Transaction(
            [fee_payer, mint],
            Message(setup_instructions, fee_payer.pubkey()),
            setup_blockhash.value.blockhash,
        )
        await rpc.send_transaction(setup_transaction)
        token = AsyncToken(rpc, mint.pubkey(), TOKEN_PROGRAM_ID, fee_payer)

        # !mark(1:6)
        create_associated_token_account_instruction = create_associated_token_account(
            payer=fee_payer.pubkey(),  # Account funding account creation.
            owner=owner.pubkey(),  # Account that owns the token account.
            mint=mint.pubkey(),  # Mint for the token this account holds.
            token_program_id=TOKEN_PROGRAM_ID,  # Token program that owns the new token account.
        )
        latest_blockhash = await rpc.get_latest_blockhash()
        transaction = Transaction(
            [fee_payer],
            Message([create_associated_token_account_instruction], fee_payer.pubkey()),
            latest_blockhash.value.blockhash,
        )
        result = await rpc.send_transaction(transaction)

        token_account_info = await token.get_account_info(associated_token_account)
        token_account = {
            key: str(value) if isinstance(value, Pubkey) else value
            for key, value in token_account_info._asdict().items()
        }

        print("Mint Address:", mint.pubkey())
        print("\nToken Account Address:", associated_token_account)
        print("Token Account:")
        print(json.dumps(token_account, indent=2))
        print("\nTransaction Signature:", result.value)

if __name__ == "__main__":
    asyncio.run(main())
```

</CodeTabs>

## How to Create a Token Account

Creating a token account requires two instructions:

1. The System Program's _rs`CreateAccount`_ instruction creates a new
   rent-exempt account and assigns the Token Program as the program owner of the
   new account.
2. The Token Program's _rs`InitializeAccount`_, _rs`InitializeAccount2`_, or
   _rs`InitializeAccount3`_ instruction initializes the new account for a mint
   and owner.

Include the _rs`CreateAccount`_ instruction and the token account initialization
instruction in the same transaction.

During token account initialization, the Token Program checks that the account
is not already initialized and is rent-exempt.

<Callout type="info">
  The section below shows how to create a token account by directly calling the
  System Program and Token Program instructions. For most applications, use the
  Associated Token Program instead. Use direct System Program and Token Program
  calls when you have a specific reason not to use an associated token account
  or when you need to create custom PDA token accounts by making CPIs to the
  System Program and Token Program instructions from your own Solana program.
</Callout>

### Source Reference

| Item                              | Description                                                                                                                        | Token Program                                                                                                  | Token Extension Program                                                                                              |
| --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| _rs`Account`_                     | The base token account fields stored in every token account.                                                                       | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/interface/src/state.rs#L84-L108)        | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/interface/src/state.rs#L99-L123)        |
| _rs`InitializeAccount`_           | A token account initialization instruction that expects the owner and rent sysvar account in its accounts list.                    | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/interface/src/instruction.rs#L45-L63)   | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/interface/src/instruction.rs#L75-L93)   |
| _rs`InitializeAccount2`_          | A token account initialization instruction that passes the owner in instruction data instead of the accounts list.                 | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/interface/src/instruction.rs#L352-L365) | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/interface/src/instruction.rs#L419-L433) |
| _rs`InitializeAccount3`_          | A token account initialization instruction that passes the owner in instruction data and does not require the rent sysvar account. | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/interface/src/instruction.rs#L377-L387) | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/interface/src/instruction.rs#L445-L456) |
| _rs`_process_initialize_account`_ | Shared processor logic for token account initialization.                                                                           | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/program/src/processor.rs#L83-L141)      | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/program/src/processor.rs#L153-L234)     |
| _rs`process_initialize_account`_  | Public handler for _rs`InitializeAccount`_.                                                                                        | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/program/src/processor.rs#L143-L150)     | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/program/src/processor.rs#L236-L240)     |
| _rs`process_initialize_account2`_ | Public handler for _rs`InitializeAccount2`_.                                                                                       | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/program/src/processor.rs#L152-L160)     | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/program/src/processor.rs#L242-L246)     |
| _rs`process_initialize_account3`_ | Public handler for _rs`InitializeAccount3`_.                                                                                       | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/program/src/processor.rs#L162-L170)     | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/program/src/processor.rs#L248-L252)     |

### Typescript

The `Kit` examples below show the recommended approach using `@solana/kit`.
Legacy examples using `@solana/web3.js` are included for reference.

#### Kit

<CodeTabs storage="token-ts-kit" flags="r">

```ts !! title="Plugin"
import { createClient, generateKeyPairSigner, lamports } from "@solana/kit";
import { solanaRpc, rpcAirdrop } from "@solana/kit-plugin-rpc";
import { generatedPayer, airdropPayer } from "@solana/kit-plugin-signer";
import { systemProgram } from "@solana-program/system";
import {
  getTokenSize,
  tokenProgram,
  TOKEN_PROGRAM_ADDRESS
} from "@solana-program/token";

const client = await createClient()
  .use(generatedPayer())
  .use(
    solanaRpc({
      rpcUrl: "http://localhost:8899",
      rpcSubscriptionsUrl: "ws://localhost:8900"
    })
  )
  .use(rpcAirdrop())
  .use(airdropPayer(lamports(1_000_000_000n)))
  // !mark[/\.use\(systemProgram\(\)\)/]
  .use(systemProgram())
  // !mark[/\.use\(tokenProgram\(\)\)/]
  .use(tokenProgram());

// !collapse(1:16) collapsed
// Setup: Create a mint for this example.
const mint = await generateKeyPairSigner();

await client.token.instructions
  .createMint({
    newMint: mint,
    decimals: 2,
    mintAuthority: client.payer.address,
    freezeAuthority: client.payer.address
  })
  .sendTransaction();

const tokenAccount = await generateKeyPairSigner();

const space = BigInt(getTokenSize());
const rent = await client.rpc.getMinimumBalanceForRentExemption(space).send();

const result = await client.sendTransaction([
  // !mark(1:10)
  client.system.instructions.createAccount({
    newAccount: tokenAccount, // New token account to create.
    lamports: rent, // Lamports funding the new account rent.
    space, // Account size in bytes.
    programAddress: TOKEN_PROGRAM_ADDRESS // Program that owns the new account.
  }),
  client.token.instructions.initializeAccount({
    account: tokenAccount.address, // Token account to initialize.
    mint: mint.address, // Mint for the token this account holds.
    owner: client.payer.address // Account that owns the token account.
  })
]);

const tokenAccountData = await client.token.accounts.token.fetch(
  tokenAccount.address
);

console.log("Mint Address:", mint.address);
console.log("\nToken Account Address:", tokenAccount.address);
console.log("Token Account:", tokenAccountData.data);
console.log("\nTransaction Signature:", result.context.signature);
```

```ts !! title="Instructions"
import { createClient, generateKeyPairSigner, lamports } from "@solana/kit";
import { solanaRpc, rpcAirdrop } from "@solana/kit-plugin-rpc";
import { generatedPayer, airdropPayer } from "@solana/kit-plugin-signer";
import { getCreateAccountInstruction } from "@solana-program/system";
import {
  fetchToken,
  getInitializeAccountInstruction,
  getInitializeMintInstruction,
  getMintSize,
  getTokenSize,
  TOKEN_PROGRAM_ADDRESS
} from "@solana-program/token";

const client = await createClient()
  .use(generatedPayer())
  .use(
    solanaRpc({
      rpcUrl: "http://localhost:8899",
      rpcSubscriptionsUrl: "ws://localhost:8900"
    })
  )
  .use(rpcAirdrop())
  .use(airdropPayer(lamports(1_000_000_000n)));

// !collapse(1:28) collapsed
// Setup: Create a mint for this example.
const mint = await generateKeyPairSigner();

const space = BigInt(getMintSize());
const rent = await client.rpc.getMinimumBalanceForRentExemption(space).send();

await client.sendTransaction([
  getCreateAccountInstruction({
    payer: client.payer,
    newAccount: mint,
    lamports: rent,
    space,
    programAddress: TOKEN_PROGRAM_ADDRESS
  }),
  getInitializeMintInstruction({
    mint: mint.address,
    decimals: 2,
    mintAuthority: client.payer.address,
    freezeAuthority: client.payer.address
  })
]);

const tokenAccount = await generateKeyPairSigner();

const tokenAccountSpace = BigInt(getTokenSize());
const tokenAccountRent = await client.rpc
  .getMinimumBalanceForRentExemption(tokenAccountSpace)
  .send();

const result = await client.sendTransaction([
  // !mark(1:12)
  getCreateAccountInstruction({
    payer: client.payer, // Account funding account creation.
    newAccount: tokenAccount, // New token account to create.
    lamports: tokenAccountRent, // Lamports funding the new account rent.
    space: tokenAccountSpace, // Account size in bytes.
    programAddress: TOKEN_PROGRAM_ADDRESS // Program that owns the new account.
  }),
  getInitializeAccountInstruction({
    account: tokenAccount.address, // Token account to initialize.
    mint: mint.address, // Mint for the token this account holds.
    owner: client.payer.address // Account that owns the token account.
  })
]);

const tokenAccountData = await fetchToken(client.rpc, tokenAccount.address);

console.log("Mint Address:", mint.address);
console.log("\nToken Account Address:", tokenAccount.address);
console.log("Token Account:", tokenAccountData.data);
console.log("\nTransaction Signature:", result.context.signature);
```

</CodeTabs>

#### Web3.js

<CodeTabs storage="token-ts-legacy" flags="r">

```ts !! title="Helper Function"
import { Connection, Keypair, LAMPORTS_PER_SOL } from "@solana/web3.js";
import {
  createAccount,
  createMint,
  getAccount,
  TOKEN_PROGRAM_ID
} from "@solana/spl-token";

// !collapse(1:28) collapsed
// Setup: create a mint before creating the token account.
const connection = new Connection("http://localhost:8899", "confirmed");
const latestBlockhash = await connection.getLatestBlockhash();

const feePayer = Keypair.generate();

const airdropSignature = await connection.requestAirdrop(
  feePayer.publicKey,
  LAMPORTS_PER_SOL
);
await connection.confirmTransaction({
  blockhash: latestBlockhash.blockhash,
  lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
  signature: airdropSignature
});

const mintPubkey = await createMint(
  connection,
  feePayer,
  feePayer.publicKey,
  feePayer.publicKey,
  2,
  Keypair.generate(),
  {
    commitment: "confirmed"
  },
  TOKEN_PROGRAM_ID
);

// !mark(1:11)
const tokenAccount = await createAccount(
  connection, // Connection to the local validator.
  feePayer, // Account paying transaction fees.
  mintPubkey, // Mint for the token this account holds.
  feePayer.publicKey, // Account that owns the token account.
  Keypair.generate(), // New token account to create.
  {
    commitment: "confirmed" // Confirmation options for the transaction.
  },
  TOKEN_PROGRAM_ID // Token program to invoke.
);

const tokenAccountData = await getAccount(
  connection,
  tokenAccount,
  "confirmed",
  TOKEN_PROGRAM_ID
);

console.log("Mint Address:", mintPubkey.toBase58());
console.log("\nToken Account Address:", tokenAccount.toBase58());
console.log("Token Account:", tokenAccountData);
```

```ts !! title="Instructions"
import {
  Connection,
  Keypair,
  sendAndConfirmTransaction,
  SystemProgram,
  Transaction,
  LAMPORTS_PER_SOL
} from "@solana/web3.js";
import {
  createInitializeMintInstruction,
  createInitializeAccountInstruction,
  ACCOUNT_SIZE,
  getAccount,
  getMinimumBalanceForRentExemptAccount,
  getMinimumBalanceForRentExemptMint,
  MINT_SIZE,
  TOKEN_PROGRAM_ID
} from "@solana/spl-token";

// !collapse(1:46) collapsed
// Setup: create a mint before creating the token account.
const connection = new Connection("http://localhost:8899", "confirmed");
const latestBlockhash = await connection.getLatestBlockhash();

const feePayer = Keypair.generate();

const airdropSignature = await connection.requestAirdrop(
  feePayer.publicKey,
  LAMPORTS_PER_SOL
);
await connection.confirmTransaction({
  blockhash: latestBlockhash.blockhash,
  lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
  signature: airdropSignature
});

const mint = Keypair.generate();
const mintRent = await getMinimumBalanceForRentExemptMint(connection);
await sendAndConfirmTransaction(
  connection,
  new Transaction({
    feePayer: feePayer.publicKey,
    blockhash: latestBlockhash.blockhash,
    lastValidBlockHeight: latestBlockhash.lastValidBlockHeight
  }).add(
    SystemProgram.createAccount({
      fromPubkey: feePayer.publicKey,
      newAccountPubkey: mint.publicKey,
      space: MINT_SIZE,
      lamports: mintRent,
      programId: TOKEN_PROGRAM_ID
    }),
    createInitializeMintInstruction(
      mint.publicKey,
      2,
      feePayer.publicKey,
      feePayer.publicKey,
      TOKEN_PROGRAM_ID
    )
  ),
  [feePayer, mint]
);

const tokenAccount = Keypair.generate();
const tokenAccountRent =
  await getMinimumBalanceForRentExemptAccount(connection);

const result = await sendAndConfirmTransaction(
  connection,
  new Transaction({
    feePayer: feePayer.publicKey,
    blockhash: latestBlockhash.blockhash,
    lastValidBlockHeight: latestBlockhash.lastValidBlockHeight
  }).add(
    // !mark(1:13)
    SystemProgram.createAccount({
      fromPubkey: feePayer.publicKey, // Account funding account creation.
      newAccountPubkey: tokenAccount.publicKey, // New token account to create.
      space: ACCOUNT_SIZE, // Account size in bytes.
      lamports: tokenAccountRent, // Lamports funding the new account rent.
      programId: TOKEN_PROGRAM_ID // Program that owns the new account.
    }),
    createInitializeAccountInstruction(
      tokenAccount.publicKey, // Token account to initialize.
      mint.publicKey, // Mint for the token this account holds.
      feePayer.publicKey, // Account that owns the token account.
      TOKEN_PROGRAM_ID
    )
  ),
  [feePayer, tokenAccount]
);

const tokenAccountData = await getAccount(
  connection,
  tokenAccount.publicKey,
  "confirmed",
  TOKEN_PROGRAM_ID
);

console.log("Mint Address:", mint.publicKey.toBase58());
console.log("\nToken Account Address:", tokenAccount.publicKey.toBase58());
console.log("Token Account:", tokenAccountData);
console.log("\nTransaction Signature:", result);
```

</CodeTabs>

### Rust

<CodeTabs storage="token-rs" flags="r">

```rust !! title="Rust"
use anyhow::Result;
use solana_client::nonblocking::rpc_client::RpcClient;
use solana_commitment_config::CommitmentConfig;
use solana_sdk::{
    program_pack::Pack,
    signature::{Keypair, Signer},
    transaction::Transaction,
};
use solana_system_interface::instruction::create_account;
use spl_token_interface::{
    id as token_program_id,
    instruction::{initialize_account, initialize_mint},
    state::{Account, Mint},
};

#[tokio::main]
async fn main() -> Result<()> {
    let client = RpcClient::new_with_commitment(
        String::from("http://localhost:8899"),
        CommitmentConfig::confirmed(),
    );

    // !collapse(1:41) collapsed
    // Setup: create a mint before creating the token account.
    let fee_payer = Keypair::new();

    let airdrop_signature = client
        .request_airdrop(&fee_payer.pubkey(), 1_000_000_000)
        .await?;
    loop {
        let confirmed = client.confirm_transaction(&airdrop_signature).await?;
        if confirmed {
            break;
        }
    }

    let mint = Keypair::new();
    let mint_rent = client
        .get_minimum_balance_for_rent_exemption(Mint::LEN)
        .await?;

    let latest_blockhash = client.get_latest_blockhash().await?;
    let setup_transaction = Transaction::new_signed_with_payer(
        &[
            create_account(
                &fee_payer.pubkey(),
                &mint.pubkey(),
                mint_rent,
                Mint::LEN as u64,
                &token_program_id(),
            ),
            initialize_mint(
                &token_program_id(),
                &mint.pubkey(),
                &fee_payer.pubkey(),
                Some(&fee_payer.pubkey()),
                2,
            )?,
        ],
        Some(&fee_payer.pubkey()),
        &[&fee_payer, &mint],
        latest_blockhash,
    );
    client.send_and_confirm_transaction(&setup_transaction).await?;

    let token_account = Keypair::new();
    let token_account_rent = client
        .get_minimum_balance_for_rent_exemption(Account::LEN)
        .await?;

    let transaction = Transaction::new_signed_with_payer(
        &[
    // !mark(1:13)
            create_account(
                &fee_payer.pubkey(), // Account funding account creation.
                &token_account.pubkey(), // New token account to create.
                token_account_rent, // Lamports funding the new account rent.
                Account::LEN as u64, // Account size in bytes.
                &token_program_id(), // Program that owns the new account.
            ),
            initialize_account(
                &token_program_id(),
                &token_account.pubkey(), // Token account to initialize.
                &mint.pubkey(), // Mint for the token this account holds.
                &fee_payer.pubkey(), // Account that owns the token account.
            )?,
        ],
        Some(&fee_payer.pubkey()),
        &[&fee_payer, &token_account],
        latest_blockhash,
    );

    let transaction_signature = client.send_and_confirm_transaction(&transaction).await?;
    let token_account_data = client.get_account(&token_account.pubkey()).await?;
    let token_data = Account::unpack(&token_account_data.data)?;

    println!("Mint Address: {}", mint.pubkey());
    println!("\nToken Account Address: {}", token_account.pubkey());
    println!("Token Account: {:#?}", token_data);
    println!("\nTransaction Signature: {}", transaction_signature);

    Ok(())
}
```

</CodeTabs>
### Python

<CodeTabs flags="r">

```py !! title="Python"
#!/usr/bin/env python3

import asyncio
import json
from solana.rpc.async_api import AsyncClient
from solders.keypair import Keypair
from solders.message import Message
from solders.pubkey import Pubkey
from solders.system_program import create_account, CreateAccountParams
from solders.transaction import Transaction
from spl.token.async_client import AsyncToken
from spl.token.instructions import (
    initialize_account,
    InitializeAccountParams,
    initialize_mint,
    InitializeMintParams,
)
from spl.token.constants import ACCOUNT_LEN, MINT_LEN, TOKEN_PROGRAM_ID

async def main():
    rpc = AsyncClient("http://localhost:8899")

    async with rpc:
        # !collapse(1:18) collapsed
        # Setup: create and initialize a mint before creating the token account.
        fee_payer = Keypair()
        airdrop_signature = (await rpc.request_airdrop(fee_payer.pubkey(), 1_000_000_000)).value
        await rpc.confirm_transaction(airdrop_signature)
        mint = Keypair()
        mint_rent = (await rpc.get_minimum_balance_for_rent_exemption(MINT_LEN)).value
        setup_instructions = [
            create_account(CreateAccountParams(from_pubkey=fee_payer.pubkey(), to_pubkey=mint.pubkey(), lamports=mint_rent, space=MINT_LEN, owner=TOKEN_PROGRAM_ID)),
            initialize_mint(InitializeMintParams(decimals=2, program_id=TOKEN_PROGRAM_ID, mint=mint.pubkey(), mint_authority=fee_payer.pubkey(), freeze_authority=fee_payer.pubkey())),
        ]
        setup_blockhash = await rpc.get_latest_blockhash()
        setup_transaction = Transaction(
            [fee_payer, mint],
            Message(setup_instructions, fee_payer.pubkey()),
            setup_blockhash.value.blockhash,
        )
        await rpc.send_transaction(setup_transaction)
        token = AsyncToken(rpc, mint.pubkey(), TOKEN_PROGRAM_ID, fee_payer)

        token_account = Keypair()
        token_account_rent = (await rpc.get_minimum_balance_for_rent_exemption(ACCOUNT_LEN)).value

        # !mark(1:19)
        create_token_account_instructions = [
            create_account(
                CreateAccountParams(
                    from_pubkey=fee_payer.pubkey(),  # Account funding account creation.
                    to_pubkey=token_account.pubkey(),  # New token account to create.
                    lamports=token_account_rent,  # Lamports funding the new account rent.
                    space=ACCOUNT_LEN,  # Account size in bytes.
                    owner=TOKEN_PROGRAM_ID,  # Program that owns the new token account.
                )
            ),
            initialize_account(
                InitializeAccountParams(
                    program_id=TOKEN_PROGRAM_ID,  # Token program to invoke.
                    account=token_account.pubkey(),  # Token account to initialize.
                    mint=mint.pubkey(),  # Mint for the token this account holds.
                    owner=fee_payer.pubkey(),  # Account that owns the token account.
                )
            ),
        ]
        latest_blockhash = await rpc.get_latest_blockhash()
        transaction = Transaction(
            [fee_payer, token_account],
            Message(create_token_account_instructions, fee_payer.pubkey()),
            latest_blockhash.value.blockhash,
        )
        result = await rpc.send_transaction(transaction)

        token_account_info = await token.get_account_info(token_account.pubkey())
        token_account_data = {
            key: str(value) if isinstance(value, Pubkey) else value
            for key, value in token_account_info._asdict().items()
        }

        print("Mint Address:", mint.pubkey())
        print("\nToken Account Address:", token_account.pubkey())
        print("Token Account:")
        print(json.dumps(token_account_data, indent=2))
        print("\nTransaction Signature:", result.value)

if __name__ == "__main__":
    asyncio.run(main())
```

</CodeTabs>
