midjourney-api
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!
Recent Updates
- 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
Quick Start
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="1262639350852882442" export CHANNEL_ID="1262639350852882445" 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
Usage in Your Project
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);
Human Verification Callback humanVerify (New)
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 (VaryRegion → WaitVaryRegion) (New)
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);
}
Video Creation (New)
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);
Route Map
- <input checked="" disabled="" type="checkbox">
/imagine
variation
upscale
reroll
blend
zoomout
vary
- <input checked="" disabled="" type="checkbox">
/info
- <input checked="" disabled="" type="checkbox">
/fast
and/relax
- <input checked="" disabled="" type="checkbox">
/prefer remix
- <input checked="" disabled="" type="checkbox">
variation (remix mode)
- <input checked="" disabled="" type="checkbox">
/describe
- <input checked="" disabled="" type="checkbox">
/shorten
- <input checked="" disabled="" type="checkbox">
/settings
reset
- <input checked="" disabled="" type="checkbox"> verify human
- <input checked="" disabled="" type="checkbox"> varyRegion & waitVaryRegion (regional painting)
- <input checked="" disabled="" type="checkbox"> animate / video virtual upscale (video creation)
- <input checked="" disabled="" type="checkbox"> proxy
- <input checked="" disabled="" type="checkbox"> niji bot
- <input checked="" disabled="" type="checkbox"> custom zoom
- <input checked="" disabled="" type="checkbox"> autoload command payload