Unofficial MidJourney API Node.js client.
English / 中文文档
Notice: This project is an enhanced fork of erictik/midjourney-api. Built upon the original project, we've added human verification monitoring, regional painting, and video creation features. Thanks to the original author for the excellent work!
- New: Human verification monitoring
humanVerify
callback function - New: Regional painting (first
VaryRegion
, thenWaitVaryRegion
after confirmation) - New: Video creation (
AnimateUpscale
/Animate
) - Face swap
- Niji bot support
- Custom zoom
- Remix mode
This project requires Node.js. Run the following commands in the project root directory:
-
Download the project code
git clone https://github.com/erictik/midjourney-api.git cd midjourney-api
-
Install dependencies
yarn # or npm npm install
-
Set environment variables
-
Get Discord TOKEN Login to Discord Press F12 or [Ctrl + Shift + I] or [Command + Option + I] to open developer tools, then enter the following code in the Console:
window.webpackChunkdiscord_app.push([ [Math.random()], {}, (req) => { for (const m of Object.keys(req.c) .map((x) => req.c[x].exports) .filter((x) => x)) { if (m.default && m.default.getToken !== undefined) { return copy(m.default.getToken()); } if (m.getToken !== undefined) { return copy(m.getToken()); } } }, ]); console.log("%cWorked!", "font-size: 50px"); console.log(`%cYour token is in the clipboard!`, "font-size: 16px");
You can also get the discord token by viewing the network Get Discord Token
-
export SERVER_ID="1262639350852882442" export CHANNEL_ID="1262639350852882445"
-
Or create a Discord server and invite the Midjourney Bot
# Copy your server URL in the browser # `https://discord.com/channels/$SERVER_ID/$CHANNEL_ID` export SERVER_ID="your-server-id" export CHANNEL_ID="your-channel-id"
-
Write environment variables to
.env
file or set them in the console#example variables, please set up yours export SERVER_ID="1082500871478329374" export CHANNEL_ID="1094892992281718894" export SALAI_TOKEN="your-discord-token"
-
Now you can run the examples
npx tsx example/imagine-ws.ts
or
yarn example:imagine # or npm npm run example:imagine
-
More usage examples
-
Installation
npm i midjourney # or yarn add midjourney
-
Using Imagine, Variation and Upscale
import { Midjourney } from "midjourney"; const client = new Midjourney({ ServerId: <string>process.env.SERVER_ID, ChannelId: <string>process.env.CHANNEL_ID, SalaiToken: <string>process.env.SALAI_TOKEN, Debug: true, Ws: true, //enable ws is required for remix mode (and custom zoom) }); await client.init(); const prompt = "Christmas dinner with spaghetti with family in a cozy house, we see interior details , simple blue&white illustration"; //imagine const Imagine = await client.Imagine(prompt, (uri: string, progress: string) => { console.log("loading", uri, "progress", progress); }); console.log(Imagine); if (!Imagine) { console.log("no message"); return; } // U1 U2 U3 U4 V1 V2 V3 V4 "Vary (Strong)" ... const V1CustomID = Imagine.options?.find((o) => o.label === "V1")?.custom; if (!V1CustomID) { console.log("no V1"); return; } // Varition V1 const Varition = await client.Custom({ msgId: <string>Imagine.id, flags: Imagine.flags, customId: V1CustomID, content: prompt, //remix mode require content loading: (uri: string, progress: string) => { console.log("loading", uri, "progress", progress); }, }); console.log(Varition); const U1CustomID = Imagine.options?.find((o) => o.label === "U1")?.custom; if (!U1CustomID) { console.log("no U1"); return; } // Upscale U1 const Upscale = await client.Custom({ msgId: <string>Imagine.id, flags: Imagine.flags, customId: U1CustomID, loading: (uri: string, progress: string) => { console.log("loading", uri, "progress", progress); }, }); if (!Upscale) { console.log("no Upscale"); return; } console.log(Upscale); const zoomout = Upscale?.options?.find((o) => o.label === "Custom Zoom"); if (!zoomout) { console.log("no zoomout"); return; } // Custom Zoom const CustomZoomout = await client.Custom({ msgId: <string>Upscale.id, flags: Upscale.flags, content: `${prompt} --zoom 2`, // Custom Zoom require content customId: zoomout.custom, loading: (uri: string, progress: string) => { console.log("loading", uri, "progress", progress); }, }); console.log(CustomZoomout);
When Discord human verification is triggered (such as requiring CAPTCHA), the SDK will provide the verification page URL through the humanVerify(url)
callback. You can display this URL to users for verification completion.
import { Midjourney } from "midjourney";
const client = new Midjourney({
ServerId: <string>process.env.SERVER_ID,
ChannelId: <string>process.env.CHANNEL_ID,
SalaiToken: <string>process.env.SALAI_TOKEN,
Debug: true,
Ws: true,
humanVerify: (url?: string) => {
// Display the URL to frontend or log it, prompting users to complete verification
console.log("Human verification required, please visit:", url);
},
});
await client.init();
Regional painting workflow:
- First call
VaryRegion
to trigger regional repainting, the returned URI is Midjourney's regional painting canvas link; - Embed this URI into your webpage (e.g., iframe), users can select regions to repaint on the canvas;
- After users complete region selection and click submit on the canvas;
- Call
WaitVaryRegion
to wait for the regional painting results.
Dependency note: Requires Ws: true
to receive real-time events and results.
import { Midjourney } from "midjourney";
const client = new Midjourney({
ServerId: <string>process.env.SERVER_ID,
ChannelId: <string>process.env.CHANNEL_ID,
SalaiToken: <string>process.env.SALAI_TOKEN,
Debug: true,
Ws: true,
});
await client.init();
const prompt = "a cozy living room, watercolor, soft light";
const imagine = await client.Imagine(prompt, (uri, progress) => {
console.log("loading", uri, progress);
});
if (!imagine) throw new Error("imagine failed");
// Step 1: Trigger regional painting, get canvas link
const varyRegionResult = await client.VaryRegion({
msgId: <string>imagine.id,
hash: <string>imagine.hash!,
flags: imagine.flags,
// Optional: provide prompt here for regional repainting
content: `${prompt}, add a red pillow on the sofa`,
loading: (uri, progress) => console.log("varyRegion", uri, progress),
});
if (varyRegionResult?.uri) {
// Important: Embed this URI into your webpage for user region selection
console.log("Regional painting canvas link:", varyRegionResult.uri);
// Example: <iframe src={varyRegionResult.uri} width="100%" height="600px"></iframe>
// Step 2: After user completes region selection and submits on canvas, wait for results
const varyResult = await client.WaitVaryRegion({
msgId: <string>imagine.id,
// Optional: provide/override prompt again
content: `${prompt}, add a red pillow on the sofa`,
loading: (uri, progress) => console.log("waitVaryRegion", uri, progress),
});
console.log("Regional painting result:", varyResult);
}
Two methods available:
AnimateUpscale
: Create video based on single sub-image (U1~U4) (virtual upscale track).Animate
: Directly trigger low/high quality video on grid image (low
/high
).
Dependency note: Recommend enabling Ws: true
for progress and results.
import { Midjourney } from "midjourney";
const client = new Midjourney({
ServerId: <string>process.env.SERVER_ID,
ChannelId: <string>process.env.CHANNEL_ID,
SalaiToken: <string>process.env.SALAI_TOKEN,
Debug: true,
Ws: true,
});
await client.init();
const prompt = "futuristic city skyline at sunset, ultra detailed";
const imagine = await client.Imagine(prompt);
if (!imagine) throw new Error("imagine failed");
// First upscale a sub-image (e.g., U1), then create video based on upscaled result
const u1 = imagine.options?.find((o) => o.label === "U1")?.custom;
if (!u1) throw new Error("no U1 option");
const upscale = await client.Custom({
msgId: <string>imagine.id,
flags: imagine.flags,
customId: u1,
});
if (!upscale) throw new Error("upscale failed");
// Method 1: Create video based on upscaled image (virtual upscale track)
const video1 = await client.AnimateUpscale({
index: 1, // Corresponds to U1
msgId: <string>upscale.id,
hash: <string>upscale.hash!,
flags: upscale.flags,
loading: (uri, progress) => console.log("video_upscale", uri, progress),
});
console.log("video1", video1);
// Method 2: Directly create video on grid image (low/high)
const video2 = await client.Animate({
msgId: <string>imagine.id,
hash: <string>imagine.hash!,
animate_type: "low", // or "high"
loading: (uri, progress) => console.log("animate", uri, progress),
});
console.log("video2", video2);
-
/imagine
variation
upscale
reroll
blend
zoomout
vary
-
/info
-
/fast
and/relax
-
/prefer remix
-
variation (remix mode)
-
/describe
-
/shorten
-
/settings
reset
- verify human
- varyRegion & waitVaryRegion (regional painting)
- animate / video virtual upscale (video creation)
- proxy
- niji bot
- custom zoom
- autoload command payload