How to get seed phrase from the logged in Internet Identity user in browser?


I’m trying to authenticate a user logged in using internet identity. I’ve tried using the seed phrase provided during the first login (signup) process, but the authenticated principal is different.

Do I need to do something else?

Here’s how I’m creating an agent using the pharse (that’s asked to be saved when signing up using internet identity):

import { Secp256k1KeyIdentity } from "@dfinity/identity-secp256k1";

const seed =
  "10000 foot xxx chunk xxxx shallow xxxx dust xxxx soon xxxxx desert ribbon fatigue section whisper xxxx wild swamp xxxx mammal plastic village xxxxx hen";

export const identityFromSeed = async (phrase: string) => {
  return Secp256k1KeyIdentity.fromSeedPhrase(phrase) as any;

export const identity = identityFromSeed(seed);

And here’s how I’m creating an agent to call one of my canisters:

const IC_HOST = "";

import { identity } from "./identity.ts";
async function createAgent(identity: Identity | Promise<Identity>) {
  const agent = new HttpAgent({
    host: IC_HOST,
  await agent.fetchRootKey();
  return agent;

I also get the following warning in the console when running the nodejs script:

Warning - an unusually formatted seed phrase has been provided. Decoding may not work as expected

Hi @harshbaz

Here is the relevant code: internet-identity/ed25519.ts at main · dfinity/internet-identity · GitHub

This gives you an Ed25519 identity which you can use to initialize the agent.

Out of curiosity: What are you building? I.e. for which use-case would you need to parse II recovery phrases?

Hello @frederikrothenberger I’m adding some tests for my CI for which I want to login using the browser and use the phrase to then authenticate from a node environment.

I copied over all the code and replaced window.crypto with just crypto (crypto being imported as node library) and then used fromMnemonicWithoutValidation but it authenticated as a different user so I guess it did not work.

Did I do something wrong?

@harshbaz: I’m not familiar with the node crypto libraries. But if it didn’t work, then yes, this suggests there is an error somewhere.

I would advise you to first isolate the relevant code to run standalone in a browser environment and then port it over to node, to help you pinpoint the issue.

Also, an easier check to see whether it worked or not, might be to compare principals (derived from the public key). For that you do not even need to interact with II to see whether it worked.

Okay, so there is a way to access web equivalent crypto module using node’s crypto.webcrypto.

Testing with the code snippet on browser:

Testing with crypto.webcrypto in node 18:

Logging in from the browser and Internet Indentity, I get:
Principal ID:

And if it matters this is how I’m printing the principal:

async function printPrincipal() {
  const { Ed25519Identity } = await import('./key')
  const agent = new HttpAgent({
    identity: Ed25519Identity,
  await agent.fetchRootKey()
  const myPrincipal = await agent.getPrincipal()
  console.log('principal:', myPrincipal.toText())

I also tried defining the host property when initialising HttpAgent:

const agent = new HttpAgent({
    host: "",

But the result remains the same.

Does changing host makes a difference? The web-app that I’m running locally runs on localhost:5173.

Logging in from the browser and Internet Indentity

Wait, are you doing a sing-in flow using II? Or are you directly using the Ed25519Identity from the recovery phrase?

If you are doing the latter, then the host should not matter.

You could also try comparing the public keys that you get from Ed25519KeyIdentity.getPublicKey()? Because this would take the agent out of the loop.

To clear it up. I’m doing the whole sign-in flow locally using II. During the flow, it asks me to save the seed phrase - this is the seed phrase that I want to use with Node to authenticate as the same user.

With my last reply, I was basically saying that Node and browser environment give the same principal. This principal however, is not the same as the one I get authenticated from the II flow.