> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hedera.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create an account

> Programmatically create a Hedera account with AccountCreateTransaction, set an ECDSA key with EVM Address from Public Key, and fund the new account with HBAR.

A Hedera account is required to interact with any network service, since every transaction and query fee is paid from an account. You can create a previewnet or testnet account on the [Hedera Developer Portal](https://portal.hedera.com/), or use a third-party wallet to generate a free [mainnet account](/learn/networks/mainnet/access).

This page covers programmatic account creation with `AccountCreateTransaction()`. The transaction must be signed and paid for by an existing account. To obtain the new account ID, request the [receipt](/native/transactions/receipt) of the transaction.

For a complete list of account properties, see the [accounts overview](/native/accounts).

<Tip>
  **Recommended default for EVM compatibility:** Create accounts with an ECDSA key and set the **EVM Address from Public Key** at creation. This enables native compatibility with EVM wallets, JSON-RPC tooling, and smart-contract interactions. Use `setECDSAKeyWithAlias()` (or `setKeyWithAlias()` with an ECDSA key) to do this in a single call.
</Tip>

***

## Transaction fees and signing

* The account paying for the transaction fee is required to sign the transaction.
* The sender also pays the `maxAutoAssociations` fee and the rent for the first auto-renewal period.
* See the transaction and query [fees](/learn/networks/mainnet/fees) table for the base transaction fee.
* Use the [Hedera fee estimator](https://hedera.com/fees) to estimate cost.

***

## Constructor

| Constructor                      | Description                                       |
| -------------------------------- | ------------------------------------------------- |
| `new AccountCreateTransaction()` | Initializes the `AccountCreateTransaction` object |

## Methods

Exactly one of `setKey`, `setKeyWithAlias`, `setECDSAKeyWithAlias`, or `setKeyWithoutAlias` is required. See [Setting the key and alias](#setting-the-key-and-alias) for which to use.

| Method                                            | Type        | Key type accepted                                                      | Requirement                                                                                                                                                                    |
| ------------------------------------------------- | ----------- | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `setKey(<key>)`                                   | Key         | PublicKey or PrivateKey                                                | Sets the account key with no EVM Address from Public Key. Accepts ED25519 or ECDSA.                                                                                            |
| `setKeyWithAlias(<key>)`                          | Key (ECDSA) | PublicKey or PrivateKey                                                | Sets the key and the EVM Address from Public Key. Java's one-argument recommended form; in other SDKs this is the two-argument overload `setKeyWithAlias(key, aliasKey)`.      |
| `setECDSAKeyWithAlias(<key>)`                     | Key (ECDSA) | PrivateKey only in Rust, C++, Swift; PublicKey or PrivateKey elsewhere | **Recommended for EVM use cases.** Sets the key and the EVM Address from Public Key in one call. Not available in Java, which uses the one-argument `setKeyWithAlias` instead. |
| `setKeyWithoutAlias(<key>)`                       | Key         | PublicKey or PrivateKey                                                | Sets the key with no EVM Address from Public Key (the account falls back to its EVM Address from Account ID). Use if you plan to rotate keys later.                            |
| `setAlias(<alias>)`                               | EvmAddress  | —                                                                      | Explicitly sets the `alias` bytes. Pair with `publicKey.toEvmAddress()` to set the EVM Address from Public Key.                                                                |
| `setInitialBalance(<initialBalance>)`             | Hbar        | —                                                                      | Optional                                                                                                                                                                       |
| `setReceiverSignatureRequired(<booleanValue>)`    | boolean     | —                                                                      | Optional                                                                                                                                                                       |
| `setMaxAutomaticTokenAssociations(<amount>)`      | int         | —                                                                      | Optional                                                                                                                                                                       |
| `setStakedAccountId(<stakedAccountId>)`           | AccountId   | —                                                                      | Optional                                                                                                                                                                       |
| `setStakedNodeId(<stakedNodeId>)`                 | long        | —                                                                      | Optional                                                                                                                                                                       |
| `setDeclineStakingReward(<declineStakingReward>)` | boolean     | —                                                                      | Optional                                                                                                                                                                       |
| `setAccountMemo(<memo>)`                          | String      | —                                                                      | Optional                                                                                                                                                                       |
| `setHighVolume(<highVolume>)`                     | boolean     | —                                                                      | Optional                                                                                                                                                                       |
| `setAutoRenewPeriod(<autoRenewPeriod>)`           | Duration    | —                                                                      | Disabled                                                                                                                                                                       |

<Note>
  ### EVM address from public key

  <a id="evm-address-from-public-key" />

  <a id="evm-address-alias-recommended-for-evm-use-cases" />

  Setting an ECDSA-derived EVM address at creation makes the account natively addressable from EVM wallets, JSON-RPC, and Solidity (`msg.sender`). The address is the rightmost 20 bytes of the Keccak-256 hash of the ECDSA public key. To enable this behavior, use the one-argument key-with-alias method for your SDK (`setECDSAKeyWithAlias()` in most SDKs, `setKeyWithAlias()` in Java). See [Setting the key and alias](#setting-the-key-and-alias) for the full breakdown.

  **Immutability:** The EVM address is bound to the original ECDSA public key and does **not** change if you later rotate keys via `CryptoUpdateTransaction`. Integrations keyed to that EVM address (smart-contract permissions, address-based access lists) will continue to reference the original address.

  **If key rotation is required:** Use `setKeyWithoutAlias()` instead. The account will fall back to its EVM Address from Account ID (the long-zero form).

  **Recovery model:** If keys are compromised or must be replaced, create a new account with a new ECDSA key, then migrate assets and state. Do not rely on key rotation to preserve the same EVM identity.
</Note>

<Info>
  #### High-volume entity creation

  This transaction supports [high-volume entity creation](/learn/core-concepts/high-volume-entity-creation) (HIP-1313). Setting `setHighVolume(true)` routes the transaction through dedicated high-volume throttle capacity with variable-rate pricing. Always pair this with `setMaxTransactionFee()` to cap your costs.
</Info>

### Maximum auto-associations

The `maxAutoAssociations` property determines how many automatic token associations an account allows.

| Value | Behavior                                                                                                                                                                                                                                                                                           |
| :---: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|  `0`  | Automatic token associations and token airdrops are not allowed. Tokens must be manually associated. This also applies when the value is less than or equal to `usedAutoAssociations`.                                                                                                             |
|  `-1` | Unlimited automatic token associations. This is the default for accounts created via [auto account creation](/learn/core-concepts/accounts/auto-account-creation) and for hollow accounts that have been completed. The sender still pays the association fee and initial rent for each new token. |
| `> 0` | Automatic token associations are limited to the specified number.                                                                                                                                                                                                                                  |

Reference: [HIP-904](https://hips.hedera.com/hip/hip-904).

***

## Setting the key and alias

`AccountCreateTransaction` provides three ways to set the account key and the EVM address. Which one you choose depends on whether you want EVM compatibility and whether you plan to rotate the account key later. The method names below use the JavaScript SDK; see the [per-SDK quick reference](#per-sdk-quick-reference) for the equivalent in each language.

| Pattern                                         | Method                           | What it does                                                                                                                                | Use when                                                                                                                                                                            |
| ----------------------------------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Key with matching EVM address** (recommended) | `setECDSAKeyWithAlias(key)`      | Sets the account key and derives the EVM Address from Public Key from the same ECDSA key. Accepts a private or public ECDSA key.            | You want a standard EVM-compatible account. The signing key and the EVM address are backed by the same ECDSA key, so `msg.sender`, EVM wallets, and JSON-RPC all resolve correctly. |
| **Key with a separate alias key**               | `setKeyWithAlias(key, aliasKey)` | Sets the account (signing) key to one key and derives the EVM address from a different ECDSA key. Both keys must sign the transaction.      | The account is controlled by one key (for example an Ed25519 key, or a different ECDSA key) but you want the EVM address derived from a separate ECDSA key.                         |
| **Key without an alias**                        | `setKeyWithoutAlias(key)`        | Sets only the account key, with no EVM Address from Public Key. The account falls back to its EVM Address from Account ID (long-zero form). | You plan to rotate or update the account key later. The EVM Address from Public Key is immutable once set, so omit it if the key is not final.                                      |

<Note>
  To assign a specific, pre-computed EVM address instead of deriving one from the key, combine `setKeyWithoutAlias(key)` with `setAlias(evmAddress)`. This is the [HIP-583](https://hips.hedera.com/hip/hip-583) pattern, useful when you already hold the target EVM address (for example, when migrating an existing EVM address).
</Note>

### Private or public key input

Whether the one-shot method accepts a **public** key or requires a **private** key depends on the SDK (see the [per-SDK quick reference](#per-sdk-quick-reference)):

* **JavaScript, Java, Python, and Go** accept either a public or a private ECDSA key. The EVM address is derived from the public component, so the choice is only about what key material you hand the builder. Pass a public key when the private key is held externally (a hardware wallet, HSM, or another party); the create transaction must still be signed by the corresponding private key.
* **Rust, C++, and Swift** accept a **private key only**. If you hold just a public key (HSM or external-signer flows), use the manual path instead: set the key without an alias and set the alias explicitly from the derived address, for example `setKeyWithoutAlias(publicKey)` with `setAlias(publicKey.toEvmAddress())`. See the [HSM-signing tutorials](/native/tutorials/advanced/hsm-signing/aws-kms).

In the **JavaScript SDK**, the four derive variants are:

| Variant                                            | Call                                           |
| -------------------------------------------------- | ---------------------------------------------- |
| Derived EVM address from a **private account key** | `setECDSAKeyWithAlias(privateKey)`             |
| Derived EVM address from a **public account key**  | `setECDSAKeyWithAlias(publicKey)`              |
| Derived EVM address from a **private alias key**   | `setKeyWithAlias(accountKey, privateAliasKey)` |
| Derived EVM address from a **public alias key**    | `setKeyWithAlias(accountKey, publicAliasKey)`  |

(In Java, the one-argument forms use `setKeyWithAlias(key)` rather than `setECDSAKeyWithAlias`.) When you use a separate alias key, both the account key and the alias key must sign the transaction.

***

## Per-SDK quick reference

| SDK        | One-shot method                    | Accepts `PublicKey`?  | `PublicKey.toEvmAddress()` returns          | `AccountId.toEvmAddress()`  |
| ---------- | ---------------------------------- | --------------------- | ------------------------------------------- | --------------------------- |
| JavaScript | `setECDSAKeyWithAlias(key)`        | Yes                   | `string` (hex, no `0x`)                     | Yes                         |
| Java       | `setKeyWithAlias(key)` (1-arg)     | Yes                   | `EvmAddress`                                | Yes                         |
| Python     | `set_key_with_alias(key)`          | Yes                   | `EvmAddress`                                | Yes                         |
| Rust       | `set_ecdsa_key_with_alias(key)`    | No, `PrivateKey` only | `Option<EvmAddress>`                        | Use `to_solidity_address()` |
| C++        | `setECDSAKeyWithAlias(key)`        | No, `PrivateKey` only | `EvmAddress` (on `ECDSAsecp256k1PublicKey`) | Use `toSolidityAddress()`   |
| Swift      | `keyWithAlias(_ privateKeyECDSA:)` | No, `PrivateKey` only | `EvmAddress?`                               | Yes (`throws`)              |
| Go         | `SetECDSAKeyWithAlias(key)`        | Yes                   | `string` (hex, no `0x`)                     | Yes                         |

<Note>
  **Java naming:** `setKeyWithAlias(key)` with one argument is Java's equivalent of `setECDSAKeyWithAlias(key)` in other SDKs. The two-argument overload `setKeyWithAlias(key, ecdsaKey)` is used when the account key and the alias-derivation key differ.

  **Long-zero address parallel:** Rust and C++ do not expose `toEvmAddress()` on `AccountId`. They expose `to_solidity_address()` / `toSolidityAddress()` instead, which returns the same long-zero form (the **EVM Address from Account ID**). Functionally equivalent, just a naming difference.

  **Swift `throws`:** Swift's `AccountId.toEvmAddress()` is declared `throws`, so call sites need `try` (e.g., `try accountId.toEvmAddress()`).
</Note>

***

## Example

<CodeGroup>
  ```javascript wrap JavaScript theme={null}
  // Create new ECDSA key
  const ecdsaPublicKey = PrivateKey.generateECDSA().publicKey;

  // Create the transaction
  const transaction = new AccountCreateTransaction()
      // Sets the EVM Address from Public Key (recommended for EVM compatibility)
      .setECDSAKeyWithAlias(ecdsaPublicKey)
      // Use .setKeyWithoutAlias(ecdsaPublicKey) if you plan to rotate keys soon after creation
      .setInitialBalance(new Hbar(1));

  // Sign the transaction with the client operator private key and submit to a Hedera network
  const txResponse = await transaction.execute(client);

  //Request the receipt of the transaction
  const receipt = await txResponse.getReceipt(client);

  //Get the account ID
  const newAccountId = receipt.accountId;

  console.log("The new account ID is " + newAccountId);

  // v2.84.0
  ```

  ```java wrap Java theme={null}
  // Create new ECDSA key
  PublicKey ecdsaPublicKey = PrivateKey.generateECDSA().getPublicKey();

  // Create the transaction
  AccountCreateTransaction transaction = new AccountCreateTransaction()
      // Sets the EVM Address from Public Key (recommended for EVM compatibility)
      .setKeyWithAlias(ecdsaPublicKey)
      // Use .setKeyWithoutAlias(ecdsaPublicKey) if you plan to rotate keys soon after creation
      .setInitialBalance(new Hbar(1));

  // Sign the transaction with the client operator private key and submit to a Hedera network
  TransactionResponse txResponse = transaction.execute(client);

  //Request the receipt of the transaction
  TransactionReceipt receipt = txResponse.getReceipt(client);

  //Get the account ID
  AccountId newAccountId = receipt.accountId;

  System.out.println("The new account ID is " + newAccountId);

  // v2.72.0
  ```

  ```go wrap Go theme={null}
  // Create new ECDSA key
  ecdsaPrivateKey, _ := hedera.PrivateKeyGenerateEcdsa()
  ecdsaPublicKey := ecdsaPrivateKey.PublicKey()

  // Create the transaction
  transaction := hedera.NewAccountCreateTransaction().
      // Sets the EVM Address from Public Key (recommended for EVM compatibility)
      SetECDSAKeyWithAlias(ecdsaPublicKey).
      // Use SetKeyWithoutAlias(ecdsaPublicKey) if you plan to rotate keys soon after creation
      SetInitialBalance(hedera.NewHbar(1))

  // Sign the transaction with the client operator private key and submit to a Hedera network
  txResponse, err := transaction.Execute(client)

  //Request the receipt of the transaction
  receipt, err := txResponse.GetReceipt(client)

  //Get the account ID
  newAccountId := *receipt.AccountID

  fmt.Printf("The new account ID is %v\n", newAccountId)

  // v2.80.0
  ```

  ```rust wrap Rust theme={null}
  // Create new ECDSA key
  let ecdsa_private_key = PrivateKey::generate_ecdsa();

  // Create the transaction
  let transaction = AccountCreateTransaction::new()
      // Sets the EVM Address from Public Key (recommended for EVM compatibility).
      // In Rust this method takes the ECDSA PrivateKey; a PublicKey is not accepted.
      .set_ecdsa_key_with_alias(ecdsa_private_key)
      // Use .set_key_without_alias(key) if you plan to rotate keys soon after creation
      .initial_balance(Hbar::new(1));

  // Sign the transaction with the client operator private key and submit to a Hedera network
  let tx_response = transaction.execute(&client).await?;

  // Request the receipt of the transaction
  let receipt = tx_response.get_receipt(&client).await?;

  // Get the account ID
  let new_account_id = receipt.account_id.unwrap();

  println!("The new account ID is {}", new_account_id);

  // v0.45.0
  ```

  ```python Python theme={null}
  # Create new ECDSA key
  ecdsa_public_key = PrivateKey.generate_ecdsa().public_key()

  # Create the transaction
  transaction = (
      AccountCreateTransaction()
      # Sets the EVM Address from Public Key (recommended for EVM compatibility)
      .set_key_with_alias(ecdsa_public_key)
      # Use .set_key_without_alias(ecdsa_public_key) if you plan to rotate keys soon after creation
      .set_initial_balance(Hbar(1))
  )

  # Sign the transaction with the client operator private key and submit to a Hedera network
  tx_response = transaction.execute(client)

  # Request the receipt of the transaction
  receipt = tx_response.get_receipt(client)

  # Get the account ID
  new_account_id = receipt.account_id

  print(f"The new account ID is {new_account_id}")

  # v0.2.7
  ```
</CodeGroup>

***

## Deriving the EVM address (`toEvmAddress` helper)

If you call `setAlias(...)` directly instead of a one-shot key-with-alias method, derive the EVM address from the ECDSA public key with the SDK helper:

<CodeGroup>
  ```javascript JavaScript theme={null}
  // publicKey.toEvmAddress() returns the EVM Address from Public Key (hex, no 0x prefix)
  const evmAddress = ecdsaPublicKey.toEvmAddress();

  const transaction = new AccountCreateTransaction()
    .setKeyWithoutAlias(ecdsaPublicKey)
    .setAlias(evmAddress)
    .setInitialBalance(new Hbar(1));
  ```

  ```java Java theme={null}
  String evmAddress = ecdsaPublicKey.toEvmAddress();

  AccountCreateTransaction transaction = new AccountCreateTransaction()
    .setKeyWithoutAlias(ecdsaPublicKey)
    .setAlias(evmAddress)
    .setInitialBalance(new Hbar(1));
  ```

  ```go Go theme={null}
  evmAddress := ecdsaPublicKey.ToEvmAddress()

  transaction := hedera.NewAccountCreateTransaction().
    SetKeyWithoutAlias(ecdsaPublicKey).
    SetAlias(evmAddress).
    SetInitialBalance(hedera.NewHbar(1))
  ```

  ```rust Rust theme={null}
  // to_evm_address() returns Option<EvmAddress> for an ECDSA public key
  let evm_address = ecdsa_public_key.to_evm_address().expect("ECDSA key has an EVM address");

  let transaction = AccountCreateTransaction::new()
    .set_key_without_alias(ecdsa_public_key)
    .alias(evm_address)
    .initial_balance(Hbar::new(1));
  ```

  ```python Python theme={null}
  # public_key.to_evm_address() returns the EVM Address from Public Key
  evm_address = ecdsa_public_key.to_evm_address()

  transaction = (
      AccountCreateTransaction()
      .set_key_without_alias(ecdsa_public_key)
      .set_alias(evm_address)
      .set_initial_balance(Hbar(1))
  )
  ```
</CodeGroup>

<Tip>
  In most cases, prefer `setECDSAKeyWithAlias(publicKey)`, which sets the key and derives the alias in one call. Use the `toEvmAddress` helper when you need the value separately (for logging, validation, or pairing with `setAlias`).
</Tip>

**Note on overloading:** `toEvmAddress` is also exposed on `AccountId` in some SDKs. `AccountId.toEvmAddress()` returns the **EVM Address from Account ID** (the long-zero form), not the **EVM Address from Public Key**. For EVM compatibility, you want the `PublicKey` variant. `AccountId.toEvmAddress()` is not implemented in Rust and is named `toSolidityAddress()` in C++.

***

## Verifying the EVM address

After creating an account, confirm the EVM Address from Public Key was set correctly using either the SDK or the mirror node.

### Using the SDK

<CodeGroup>
  ```javascript JavaScript theme={null}
  const info = await new AccountInfoQuery()
    .setAccountId(newAccountId)
    .execute(client);
  console.log(`EVM address: 0x${info.contractAccountId}`);
  ```

  ```java Java theme={null}
  AccountInfo info = new AccountInfoQuery()
    .setAccountId(newAccountId)
    .execute(client);
  System.out.println("EVM address: 0x" + info.contractAccountId);
  ```

  ```python Python theme={null}
  info = AccountInfoQuery().set_account_id(new_account_id).execute(client)
  print(f"EVM address: 0x{info.contract_account_id}")
  ```

  ```go Go theme={null}
  info, _ := hedera.NewAccountInfoQuery().
    SetAccountID(newAccountId).
    Execute(client)
  fmt.Printf("EVM address: 0x%s\n", info.ContractAccountID)
  ```
</CodeGroup>

<Note>
  If the account was created with `setKeyWithoutAlias(...)`, `contractAccountId` returns the **EVM Address from Account ID** (long-zero form, starting with 24 zero hex characters). If it was created with `setECDSAKeyWithAlias(...)` or equivalent, it returns the **EVM Address from Public Key**.
</Note>

### Using the mirror node REST API

```bash theme={null}
# Look up by account ID
curl https://mainnet.mirrornode.hedera.com/api/v1/accounts/0.0.1234

# Look up by EVM address
curl https://mainnet.mirrornode.hedera.com/api/v1/accounts/0xab...cd
```

The `evm_address` field in the response is the canonical EVM address for the account.

***

## Common pitfalls

<Warning>
  **Creating an ECDSA account with `setKey()` only.** The account is valid and can hold HBAR, but it has no **EVM Address from Public Key**. It falls back to its **EVM Address from Account ID** (long-zero form), which means:

  * It is not natively addressable from MetaMask or other EVM wallets keyed to the public-key EVM address.
  * Solidity contracts that compare `msg.sender` against the expected EVM address will not match.
  * JSON-RPC tooling expecting an ECDSA-derived address sees an unexpected long-zero address.

  Use `setECDSAKeyWithAlias(publicKey)` (or `setKeyWithAlias(publicKey)` with an ECDSA key) instead.
</Warning>

<Warning>
  **Using deprecated `PrivateKey.generate()`.** This helper silently returns an ED25519 key, which cannot be used to derive an EVM address. Use `PrivateKey.generateECDSA()` for new accounts.
</Warning>

### Common consensus errors

| Error code                  | Cause                                                                                                                           | Resolution                                                                                            |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `INVALID_ALIAS_KEY`         | Alias is not derivable from the supplied key (typically an ED25519 key was used in an ECDSA alias flow).                        | Use `PrivateKey.generateECDSA()` (or the equivalent in your SDK).                                     |
| `INVALID_SIGNATURE`         | Two-key form (`setKeyWithAlias(key, ecdsaKey)`) was not signed by both the account key and the alias key.                       | Sign the transaction with both keys before submitting.                                                |
| `ALIAS_ALREADY_ASSIGNED`    | The EVM address is already in use by another account (for example, a hollow account previously received funds at this address). | Generate a fresh ECDSA key, or complete the existing hollow account by signing a transaction from it. |
| `ACCOUNT_ID_DOES_NOT_EXIST` | A query referenced an EVM address with no associated account.                                                                   | Confirm the account was created and the receipt returned `SUCCESS`.                                   |

***

## Get transaction values

| Method                           | Type      | Description                                                                                                     |
| -------------------------------- | --------- | --------------------------------------------------------------------------------------------------------------- |
| `getKey()`                       | Key       | Returns the public key on the account                                                                           |
| `getInitialBalance()`            | Hbar      | Returns the initial balance of the account                                                                      |
| `getAutoRenewPeriod()`           | Duration  | Returns the auto-renew period on the account                                                                    |
| `getDeclineStakingReward()`      | boolean   | Returns whether the account declined staking rewards                                                            |
| `getStakedNodeId()`              | long      | Returns the staked node ID                                                                                      |
| `getStakedAccountId()`           | AccountId | Returns the staked account ID                                                                                   |
| `getReceiverSignatureRequired()` | boolean   | Returns whether the receiver signature is required                                                              |
| `getHighVolume()`                | boolean   | Returns whether this transaction uses [high-volume throttles](/learn/core-concepts/high-volume-entity-creation) |
