Skip to content
rounder

The SDK

@roundertools/sdk gives Node.js the tools from roundertools.com as typed functions. It's the site's own code, bundled for Node, so results match what the site makes. Everything runs in your process; there are no API keys and no network requests.

terminal
npm install @roundertools/sdk

It needs Node 22.13 or newer. Two things are optional: @napi-rs/canvas (for PDF to JPG and for GIF, BMP or SVG input) and an ffmpeg on your PATH, or at ROUNDERTOOLS_FFMPEG, for video and audio.

Basics

node.js
import { pdf, image } from '@roundertools/sdk';

// paths, file: URLs, bytes or Blobs all work as input
const small = await pdf.compress('report.pdf', { target: '1mb' });
console.log(small.size, small.meta.fits);   // 412345 true
await small.save();                         // ./report-compressed.pdf, never over an existing file

const webp = await image.convert('photo.png', { to: 'webp', quality: 80 });
await webp.save('out/');                    // out/photo.webp

Each function returns a FileOutput (or a list of them, or text): data (the bytes),name, mime, size, meta (details like page counts, pixel sizes or whether a target was met) and warnings. save(path?) writes it atomically and refuses to replace an existing file unless you pass { overwrite: true }.

Sizes are decimal, like the site's targets: "100kb" is 100,000 bytes. Use "100KiB" for 102,400.

Every tool by name

node.js
import { run, describe, ops } from '@roundertools/sdk';

// any tool by its slug, including the site's preset pages
const r = await run('compress-pdf-to-100kb', ['scan.pdf']);
await r.files[0].save();

describe('compress-pdf').options;   // JSON Schema of its options
ops.map((o) => o.slug);             // every tool the SDK has

Progress and cancelling

node.js
const controller = new AbortController();
const out = await pdf.compress('big.pdf', { level: 'strong' }, {
  signal: controller.signal,
  onProgress: (p) => console.log(p.stage, p.done, p.total),
});

Errors

Everything throws a RounderError with a plain-English message, an optional hint, and a code: needs-password, wrong-password, damaged,unsupported-input, unsupported-codec, missing-dependency,invalid-options, out-of-memory, aborted, exists or failed.

node.js
import { RounderError } from '@roundertools/sdk';

try {
  await pdf.unlock('statement.pdf');
} catch (e) {
  if (e instanceof RounderError && e.code === 'needs-password') {
    // ask for it, then: pdf.unlock('statement.pdf', { password })
  }
}

The functions

pdf

  • pdf.merge(files, options?): Combine PDFs (and JPG or PNG images) into one PDF, in the order given.
  • pdf.split(file, options?): Cut a PDF into several files: by page ranges, every N pages, or parts under a size limit.
  • pdf.compress(file, options?): Shrink a PDF: downscale and recompress its photos, then repack the file losslessly, or hit a size target.
  • pdf.protect(file, options?): Lock a PDF with a password (AES-256), and optionally stop printing, copying or editing.
  • pdf.unlock(file, options?): Remove the password and restrictions from a PDF you can open.
  • pdf.organize(file, options?): Reorder, rotate and delete pages of a PDF.
  • pdf.addPageNumbers(file, options?): Stamp page numbers on a PDF, in any corner, with "Page 1 of N" style labels.
  • pdf.watermark(file, options?): Stamp text like CONFIDENTIAL across the pages of a PDF.
  • pdf.fromImages(files, options?): Turn photos and images (JPG, PNG, WebP, AVIF) into one PDF, one image per page.
  • pdf.toText(file, options?): Pull the text out of a PDF, in reading order, as plain text or Markdown.
  • pdf.toImages(file, options?): Save each PDF page as a JPG or PNG image.
  • pdf.extractImages(file, options?): Save the photos and pictures inside a PDF as the original JPGs, or as PNGs.

image

  • image.convert(file, options?): Convert images between JPG, PNG, WebP and AVIF.
  • image.compress(file, options?): Make images smaller: re-encode at a lower quality, or hit a size target.
  • image.resize(file, options?): Resize images by pixels, by percent, or down to a file size.
  • image.crop(file, options?): Crop an image to a box in pixels, or to an aspect ratio from the center.
  • image.rotate(file, options?): Turn images by 90, 180 or 270 degrees, or flip them.
  • image.stripMetadata(file, options?): Remove EXIF, GPS location, XMP and other metadata from JPG, PNG and WebP, without re-encoding.

files

  • files.zip(files, options?): Pack files into one ZIP archive.
  • files.unzip(file, options?): Extract the files from a ZIP archive, safely: no paths outside the output folder, no symlinks, size caps.
  • files.checksum(file, options?): MD5, SHA-1, SHA-256, SHA-384, SHA-512 and CRC32 of a file, and a check against an expected value.
  • files.info(file, options?): What a file is: PDF pages, encryption and metadata; image size and format; video and audio streams and length.

media

  • media.compress(file, options?): Shrink a video to a size target (like 25mb for Discord or email) or by a quality preset.
  • media.convert(file, options?): Convert videos to MP4, WebM, MOV or MKV, or pull the sound out as MP3, M4A or WAV.
  • media.trim(file, options?): Cut a video down to the part between two times.
  • media.mute(file, options?): Remove the sound from a video, without re-encoding the picture.
  • media.toGif(file, options?): Turn a video clip into an animated GIF with a per-clip palette.
  • media.toAudio(file, options?): Save the soundtrack of a video as MP3, M4A, OGG, WAV or FLAC.
  • media.convertAudio(file, options?): Convert audio between MP3, M4A, WAV, OGG and FLAC.

The options of each are on the tool table, and your editor shows them as you type.

try