prusalink-client
v1.0.1
Published
Unofficial Node.js client for Prusa printers via the PrusaLink API (Core One, MK4, XL, MINI+)
Maintainers
Readme
prusalink-client
Unofficial Node.js client for Prusa printers via the PrusaLink API. Not affiliated with or endorsed by Prusa Research.
A zero-dependency Node.js client for the Prusa Core One, MK4, XL, and MINI+ using the PrusaLink v1 REST API with HTTP Digest authentication.
- No external packages — uses Node 20+ built-in
fetchandcrypto - Full TypeScript types included
- Covers the full PrusaLink v1 API: status, jobs, files, storage, cameras, uploads
- Includes a CLI (
prusalink) and an importablePrusaClientclass
Requirements
- Node.js 20.6 or later
- Prusa Core One (or MK4/XL/MINI+) running PrusaLink firmware 4.7.0+
- Printer and computer on the same local network
Installation
npm install prusalink-clientSetup
Configure credentials
Copy the example config and fill in your printer's details:
cp .env.example .envEdit .env:
PRUSA_HOST=192.168.1.x
PRUSA_USERNAME=maker
PRUSA_PASSWORD=your_password_hereFinding your credentials: On the printer touchscreen go to Settings → Network → Login credentials. The username is
makerby default.
The .env file is gitignored and will never be committed.
CLI Usage
After installing, credentials are read from environment variables:
# With a .env file (Node 20.6+)
node --env-file=.env $(which prusalink) status
# Or export directly
export PRUSA_HOST=192.168.1.x
export PRUSA_USERNAME=maker
export PRUSA_PASSWORD=yourpassword
prusalink statusWhen using from this repo directly:
node --env-file=.env bin/prusalink.js <command>
# or via npm scripts:
npm run statusCommands
| Command | Description |
|---------|-------------|
| status | Printer state, temperatures, fan speeds, current job progress |
| job | Active print job details (id, progress, time remaining) |
| files | List files on the printer (auto-detects USB/local storage) |
| storage | Storage devices with available free space |
| info | Printer serial number, nozzle diameter, hostname |
| cameras | List connected cameras |
| snap | Capture a camera snapshot and save as snapshot.png |
| legacy | OctoPrint-compatible printer + job state (fallback) |
Example output
=== Printer Status ===
State : PRINTING
Nozzle temp : 205.4°C / target 205°C
Bed temp : 60°C / target 60°C
Speed : 100%
Flow : 100%
Z axis : 17 mm
Hotend fan : 8495 RPM
Print fan : 5129 RPM
=== Current Job ===
File : (on USB/SD)
Progress : 79.0%
Time left : 0h 23mUsing PrusaClient in Your Own Script
Import the client class directly for use in automation, dashboards, bots, etc.
import { PrusaClient } from "prusalink-client";
const printer = new PrusaClient({
host: process.env.PRUSA_HOST,
username: process.env.PRUSA_USERNAME,
password: process.env.PRUSA_PASSWORD,
});Run your script with:
node --env-file=.env your-script.jsAPI Reference
printer.version()
Returns PrusaLink API version, firmware version, and server info.
const v = await printer.version();
// { api: "2.0.0", firmware: "6.5.3+12780", server: "2.1.2", hostname: "prusa-core-one", ... }printer.info()
Returns static printer details.
const info = await printer.info();
// { serial: "4914-...", nozzle_diameter: 0.4, mmu: false, hostname: "prusa-core-one", min_extrusion_temp: 170 }printer.status()
Main polling endpoint. Returns combined printer state, temperatures, and active job.
const status = await printer.status();
status.printer.state // "IDLE" | "PRINTING" | "PAUSED" | "FINISHED" | "ERROR" | ...
status.printer.temp_nozzle // current nozzle temp (°C)
status.printer.target_nozzle // target nozzle temp (°C)
status.printer.temp_bed // current bed temp (°C)
status.printer.target_bed // target bed temp (°C)
status.printer.axis_z // Z position (mm)
status.printer.speed // speed multiplier (%)
status.printer.flow // flow rate (%)
status.printer.fan_hotend // hotend fan RPM
status.printer.fan_print // print fan RPM
status.job?.progress // print progress (0-100)
status.job?.time_remaining // seconds remaining
status.job?.time_printing // seconds elapsed
status.job?.id // job ID (use for pause/cancel)printer.job()
Returns the active job object, or null if nothing is printing.
const job = await printer.job();
if (job) {
console.log(`Job #${job.id} — ${job.progress}% complete`);
}printer.pauseJob(id)
printer.resumeJob(id)
printer.cancelJob(id)
Pause, resume, or cancel a job by its ID.
const status = await printer.status();
const jobId = status.job?.id;
await printer.pauseJob(jobId);
await printer.resumeJob(jobId);
await printer.cancelJob(jobId);printer.files(storage, path)
List files on the printer. storage is "local", "usb", or "sdcard". Path defaults to "/".
const data = await printer.files("usb", "/");
for (const f of data.children ?? []) {
console.log(f.name, f.size);
}printer.printFile(storage, path)
Start printing a file that already exists on the printer.
await printer.printFile("usb", "/my-model.bgcode");printer.uploadFile(storage, remotePath, data, options)
Upload a .bgcode or .gcode file to the printer.
import { readFileSync } from "fs";
const file = readFileSync("./my-model.bgcode");
await printer.uploadFile("usb", "/my-model.bgcode", file, {
printAfterUpload: true, // start printing immediately (default: false)
overwrite: true, // overwrite if file exists (default: false)
});printer.deleteFile(storage, path)
Delete a file from the printer.
await printer.deleteFile("usb", "/old-model.bgcode");printer.storage()
Returns available storage devices with capacity info.
const data = await printer.storage();
for (const s of data.storage_list) {
console.log(s.type, s.path, s.available);
}printer.transfer()
Returns the current file transfer progress, or null if no transfer is active.
const t = await printer.transfer();
if (t) console.log(`Transfer: ${t.progress}%`);printer.cameras()
Returns a list of connected cameras and their configuration.
const cams = await printer.cameras();printer.snapshot(cameraId?)
Returns an ArrayBuffer containing a PNG image from the camera. Omit cameraId to use the default camera.
import { writeFileSync } from "fs";
const buf = await printer.snapshot();
writeFileSync("snapshot.png", Buffer.from(buf));printer.reboot()
printer.restartLink()
Reboot the printer or restart the PrusaLink service only.
await printer.restartLink(); // restarts PrusaLink, not the full printer
await printer.reboot(); // full printer rebootLegacy OctoPrint-compatible endpoints
These mirror the OctoPrint API and are useful as a fallback or for compatibility with existing OctoPrint tooling.
await printer.legacyPrinter(); // GET /api/printer
await printer.legacyJob(); // GET /api/job
await printer.legacyFiles(); // GET /api/files/localExample: Poll until print finishes
import { PrusaClient } from "./src/client.js";
const printer = new PrusaClient({
host: process.env.PRUSA_HOST,
username: process.env.PRUSA_USERNAME,
password: process.env.PRUSA_PASSWORD,
});
async function waitForFinish(intervalMs = 10000) {
console.log("Watching print job...");
while (true) {
const status = await printer.status();
const state = status.printer.state;
const progress = status.job?.progress ?? 0;
const remaining = status.job?.time_remaining;
const mins = remaining != null ? Math.ceil(remaining / 60) : "?";
console.log(`[${new Date().toLocaleTimeString()}] ${state} — ${progress}% — ${mins}m remaining`);
if (state === "FINISHED" || state === "STOPPED" || state === "ERROR") {
console.log(`Print ended with state: ${state}`);
break;
}
await new Promise(r => setTimeout(r, intervalMs));
}
}
waitForFinish();Run with:
node --env-file=.env poll.jsExample: Upload and print a file
import { readFileSync } from "fs";
import { PrusaClient } from "./src/client.js";
const printer = new PrusaClient({
host: process.env.PRUSA_HOST,
username: process.env.PRUSA_USERNAME,
password: process.env.PRUSA_PASSWORD,
});
const file = readFileSync("./my-model.bgcode");
await printer.uploadFile("usb", "/my-model.bgcode", file, {
printAfterUpload: true,
overwrite: true,
});
console.log("Uploaded and started printing.");Project Structure
prusa-core-one-api/
├── src/
│ ├── client.js # PrusaClient class — all API methods
│ ├── digest.js # HTTP Digest auth (native fetch + crypto)
│ └── index.js # CLI runner
├── .env # Your credentials (gitignored)
├── .env.example # Safe template to share/commit
├── .gitignore
└── package.jsonAuthentication Notes
The Prusa Core One uses HTTP Digest (MD5) authentication — not Basic auth or API keys. This client implements Digest auth from scratch using Node's built-in crypto module, so no third-party packages are required.
The legacy /api/* endpoints technically support an X-API-Key header, but Digest is the recommended and more compatible method for firmware 6.x+.
Supported Printers
This client targets the Prusa Core One but works with any PrusaLink-enabled printer running API v2.0.0+:
| Printer | Min Firmware | |---------|-------------| | Core One | 6.x | | MK4 / MK4S | 4.7.0 | | XL | 4.7.0 | | MINI / MINI+ | 5.1.0 | | MK3.9 | 4.7.0 |
Credits & Resources
This client was built using the following resources:
Official Prusa Sources
- prusa3d/Prusa-Link-Web — Official Prusa repository containing the OpenAPI specifications (
spec/openapi.yamlandspec/openapi-legacy.yaml) that define all PrusaLink v1 and legacy API endpoints, schemas, and authentication requirements. - Prusa Connect Camera API — Prusa help article documenting the camera streaming and snapshot API.
Community & Reference Implementations
- jamesgopsill/prusa-link — Community TypeScript/Node.js client for PrusaLink, used as a reference for API method structure and authentication patterns. MIT license.
- PrusaLinkPy — Python client for PrusaLink, used as a reference implementation for endpoint behavior and response handling.
Integration Documentation
- Home Assistant PrusaLink Integration — Documents firmware version requirements, credential setup, and real-world API behavior across printer models.
- DeepWiki — prusa3d/prusa-link-web API Reference — Synthesized API reference derived from the official Prusa-Link-Web repository.
This is an unofficial project. Prusa, PrusaLink, and Prusa Connect are trademarks of Prusa Research a.s.
