---
title: Freeze Account
description:
  Freeze a token account with the mint's freeze authority to block transfers,
  burns, and delegate changes.
url: /docs/tokens/basics/freeze-account
type: tutorial
prerequisites:
  - /docs/tokens/basics/create-mint
  - /docs/tokens/basics/create-token-account
related:
  - /docs/tokens/basics/thaw-account
  - /docs/tokens/basics/set-authority
  - /docs/tokens/basics/close-account
---

## What Does Freezing a Token Account Do?

Freezing a token account keeps the same owner, mint, and balance, but prevents
the token account from receiving, transferring, or burning tokens until the
token account is thawed.

A frozen account can still be closed if the frozen account has a zero token
balance.

Only a mint that still has a freeze authority can freeze token accounts. If a
mint's freeze authority is revoked, accounts for that mint can no longer be
frozen.

## How to Freeze a Token Account

Freezing a token account uses the Token Program's _rs`FreezeAccount`_
instruction.

The _rs`FreezeAccount`_ instruction verifies that the token account belongs to
the mint and that the signer is the mint's freeze authority, then changes the
token account state from initialized to frozen.

[Native token accounts](/docs/tokens/basics/sync-native) do not support
freezing.

### Source Reference

| Item                                | Description                                                                        | Token Program                                                                                                  | Token Extension Program                                                                                              |
| ----------------------------------- | ---------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| _rs`Mint`_                          | The mint state stores the optional freeze authority used to freeze token accounts. | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/interface/src/state.rs#L13-L30)         | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/interface/src/state.rs#L25-L42)         |
| _rs`AccountState`_                  | The token account states, including _rs`Initialized`_ and _rs`Frozen`_.            | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/interface/src/state.rs#L185-L195)       | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/interface/src/state.rs#L203-L213)       |
| _rs`FreezeAccount`_                 | An instruction that changes a token account into the frozen state.                 | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/interface/src/instruction.rs#L213-L228) | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/interface/src/instruction.rs#L276-L291) |
| _rs`process_toggle_freeze_account`_ | Shared processor logic for freezing and thawing token accounts.                    | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/program/src/processor.rs#L713-L754)     | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/program/src/processor.rs#L1293-L1341)   |

### 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 {
  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());

const mint = await generateKeyPairSigner();

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

// !collapse(1:16) collapsed
// Setup: create a mint and fund the payer's ATA before freezing the token account.
await client.sendTransaction([
  client.token.instructions.createMint({
    newMint: mint,
    decimals: 2,
    mintAuthority: client.payer.address,
    freezeAuthority: client.payer.address
  }),
  await client.token.instructions.mintToATA({
    mint: mint.address,
    owner: client.payer.address,
    mintAuthority: client.payer,
    amount: 100n,
    decimals: 2
  })
]);

const result = await client.token.instructions
  // !mark(1:5)
  .freezeAccount({
    account: tokenAccount, // Token account to freeze.
    mint: mint.address, // Mint for the token account being frozen.
    owner: client.payer // Freeze authority approving this change.
  })
  .sendTransaction();

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

console.log("Mint Address:", mint.address);
console.log("\nToken Account Address:", tokenAccount);
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 {
  fetchToken,
  findAssociatedTokenPda,
  getCreateMintInstructionPlan,
  getFreezeAccountInstruction,
  getMintToATAInstructionPlanAsync,
  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)));

const mint = await generateKeyPairSigner();

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

// !collapse(1:18) collapsed
// Setup: create a mint and fund the payer's ATA before freezing the token account.
await client.sendTransaction([
  getCreateMintInstructionPlan({
    payer: client.payer,
    newMint: mint,
    decimals: 2,
    mintAuthority: client.payer.address,
    freezeAuthority: client.payer.address
  }),
  await getMintToATAInstructionPlanAsync({
    payer: client.payer,
    mint: mint.address,
    owner: client.payer.address,
    mintAuthority: client.payer,
    amount: 100n,
    decimals: 2
  })
]);

const result = await client.sendTransaction([
  // !mark(1:5)
  getFreezeAccountInstruction({
    account: tokenAccount, // Token account to freeze.
    mint: mint.address, // Mint for the token account being frozen.
    owner: client.payer // Freeze authority approving this change.
  })
]);

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

console.log("Mint Address:", mint.address);
console.log("\nToken Account Address:", tokenAccount);
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 {
  createAssociatedTokenAccount,
  freezeAccount,
  createMint,
  getAccount,
  mintToChecked,
  TOKEN_PROGRAM_ID
} from "@solana/spl-token";
import { Connection, Keypair, LAMPORTS_PER_SOL } from "@solana/web3.js";

// !collapse(1:54) collapsed
// Setup: create a mint and fund the payer's ATA before freezing 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
);

const associatedTokenAccount = await createAssociatedTokenAccount(
  connection,
  feePayer,
  mintPubkey,
  feePayer.publicKey,
  {
    commitment: "confirmed"
  },
  TOKEN_PROGRAM_ID
);

await mintToChecked(
  connection,
  feePayer,
  mintPubkey,
  associatedTokenAccount,
  feePayer,
  100,
  2,
  [],
  {
    commitment: "confirmed"
  },
  TOKEN_PROGRAM_ID
);

// !mark(1:12)
const result = await freezeAccount(
  connection, // Connection to the local validator.
  feePayer, // Account paying transaction fees.
  associatedTokenAccount, // Token account to freeze.
  mintPubkey, // Mint for the token account being frozen.
  feePayer, // Freeze authority approving this change.
  [], // Additional multisig signers.
  {
    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);
console.log("\nTransaction Signature:", result);
```

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

// !collapse(1:67) collapsed
// Setup: create a mint and fund the payer's ATA before freezing 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);
const associatedTokenAccount = getAssociatedTokenAddressSync(
  mint.publicKey,
  feePayer.publicKey,
  false,
  TOKEN_PROGRAM_ID,
  ASSOCIATED_TOKEN_PROGRAM_ID
);

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
    ),
    createAssociatedTokenAccountInstruction(
      feePayer.publicKey,
      associatedTokenAccount,
      feePayer.publicKey,
      mint.publicKey,
      TOKEN_PROGRAM_ID,
      ASSOCIATED_TOKEN_PROGRAM_ID
    ),
    createMintToCheckedInstruction(
      mint.publicKey,
      associatedTokenAccount,
      feePayer.publicKey,
      100,
      2,
      [],
      TOKEN_PROGRAM_ID
    )
  ),
  [feePayer, mint]
);

const freezeBlockhash = await connection.getLatestBlockhash();
const result = await sendAndConfirmTransaction(
  connection,
  new Transaction({
    feePayer: feePayer.publicKey,
    blockhash: freezeBlockhash.blockhash,
    lastValidBlockHeight: freezeBlockhash.lastValidBlockHeight
  }).add(
    // !mark(1:7)
    createFreezeAccountInstruction(
      associatedTokenAccount, // Token account to freeze.
      mint.publicKey, // Mint for the token account being frozen.
      feePayer.publicKey, // Freeze authority approving this change.
      [], // Additional multisig signers.
      TOKEN_PROGRAM_ID // Token program to invoke.
    )
  ),
  [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::{freeze_account, initialize_mint, mint_to_checked},
    state::{Account, Mint},
};

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

    // !collapse(1:62) collapsed
    // Setup: create a mint and fund the payer's ATA before freezing the token account.
    let fee_payer = Keypair::new();
    let decimals = 2;

    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 associated_token_address = get_associated_token_address(
        &fee_payer.pubkey(),
        &mint.pubkey(),
    );
    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()),
                decimals,
            )?,
            create_associated_token_account(
                &fee_payer.pubkey(),
                &fee_payer.pubkey(),
                &mint.pubkey(),
                &token_program_id(),
            ),
            mint_to_checked(
                &token_program_id(),
                &mint.pubkey(),
                &associated_token_address,
                &fee_payer.pubkey(),
                &[],
                100,
                decimals,
            )?,
        ],
        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:7)
            freeze_account(
                &token_program_id(), // Token program to invoke.
                &associated_token_address, // Token account to freeze.
                &mint.pubkey(), // Mint for the token account being frozen.
                &fee_payer.pubkey(), // Freeze authority approving this change.
                &[], // Additional multisig signers.
            )?,
        ],
        Some(&fee_payer.pubkey()),
        &[&fee_payer],
        latest_blockhash,
    );

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

    println!("Mint Address: {}", mint.pubkey());
    println!(
        "\nAssociated Token Account Address: {}",
        associated_token_address
    );
    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,
    freeze_account,
    FreezeAccountParams,
    get_associated_token_address,
    initialize_mint,
    InitializeMintParams,
    mint_to_checked,
    MintToCheckedParams,
)
from spl.token.constants import MINT_LEN, TOKEN_PROGRAM_ID

DECIMALS = 2
AMOUNT_TO_MINT = 100

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

    async with rpc:
        # !collapse(1:21) collapsed
        # Setup: create a mint, token account, and initial token balance before freezing 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()
        token_account_address = get_associated_token_address(fee_payer.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=DECIMALS, program_id=TOKEN_PROGRAM_ID, mint=mint.pubkey(), mint_authority=fee_payer.pubkey(), freeze_authority=fee_payer.pubkey())),
            create_associated_token_account(fee_payer.pubkey(), fee_payer.pubkey(), mint.pubkey(), TOKEN_PROGRAM_ID),
            mint_to_checked(MintToCheckedParams(program_id=TOKEN_PROGRAM_ID, mint=mint.pubkey(), dest=token_account_address, mint_authority=fee_payer.pubkey(), amount=AMOUNT_TO_MINT, decimals=DECIMALS)),
        ]
        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:8)
        freeze_account_instruction = freeze_account(
            FreezeAccountParams(
                program_id=TOKEN_PROGRAM_ID,  # Token program to invoke.
                account=token_account_address,  # Token account to freeze.
                mint=mint.pubkey(),  # Mint for the token account being frozen.
                authority=fee_payer.pubkey(),  # Freeze authority approving the freeze.
            )
        )
        latest_blockhash = await rpc.get_latest_blockhash()
        transaction = Transaction(
            [fee_payer],
            Message([freeze_account_instruction], fee_payer.pubkey()),
            latest_blockhash.value.blockhash,
        )
        result = await rpc.send_transaction(transaction)

        token_account_info = await token.get_account_info(token_account_address)
        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:", token_account_address)
        print("Token Account:")
        print(json.dumps(token_account, indent=2))
        print("\nTransaction Signature:", result.value)

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

</CodeTabs>
