
A lightweight TypeScript client for Gotenberg’s HTTP API. Use it against your own Gotenberg container or against the Chromiumly hosted API—same client, different backend.
| Self‑hosted Gotenberg | Chromiumly hosted API | |
|---|---|---|
| What it is | Official open‑source PDF stack (Docker image) | Managed service at https://api.chromiumly.dev |
| What Chromiumly calls | Documented Gotenberg routes (Chromium, LibreOffice, PDF engines, …) | Those same routes, plus Templates (not in open‑source Gotenberg) |
| Configuration | GOTENBERG_ENDPOINT |
CHROMIUMLY_API_KEY (no endpoint) |
Everything in this README that maps to gotenberg.dev applies to both backends unless a section says otherwise. Templates are Chromiumly hosted API only—they are not a Gotenberg feature and do not work with a self‑hosted instance.
Chromiumly provides a managed API at https://api.chromiumly.dev. Hosted API support was introduced in chromiumly@5.0.0 and is available only in Chromiumly 5.0.0+. If you prefer not to run Gotenberg yourself, you avoid Docker and server ops. Sign up at https://chromiumly.dev, get an API key, and call the same conversion routes as with self‑hosting. The hosted API also exposes Templates (invoice PDFs from structured data), which are not available on self‑hosted Gotenberg.
When using the hosted API, you do not need to set GOTENBERG_ENDPOINT. Just provide your API key:
CHROMIUMLY_API_KEY=your-api-key
Once the environment variable is set, Chromiumly will automatically send all requests to the hosted API using your key.
You can also configure the hosted API programmatically without an endpoint:
import { Chromiumly } from "chromiumly";
Chromiumly.configure({
apiKey: "your-api-key",
});
import { UrlConverter } from "chromiumly";
async function run() {
const urlConverter = new UrlConverter();
const buffer = await urlConverter.convert({
url: "https://www.example.com/",
});
// Write the buffer to disk, send it over HTTP, etc.
}
run();
Using npm:
npm install chromiumly
Using yarn:
yarn add chromiumly
If you are using the hosted API key option at https://api.chromiumly.dev, you do not need Docker or a local Gotenberg instance — the service is fully managed for you.
If you prefer to self‑host Gotenberg, be sure you install Docker if you have not already done so.
After that, you can start a default Docker container of Gotenberg as follows:
docker run --rm -p 3000:3000 gotenberg/gotenberg:8
Chromiumly supports configurations via both dotenv and config configuration libraries or directly via code to add a Gotenberg endpoint to your project when you are self‑hosting.
GOTENBERG_ENDPOINT=http://localhost:3000
{
"gotenberg": {
"endpoint": "http://localhost:3000"
}
}
import { Chromiumly } from "chromiumly";
Chromiumly.configure({ endpoint: "http://localhost:3000" });
Gotenberg introduces basic authentication support starting from version 8.4.0. Suppose you are running a Docker container using the command below:
docker run --rm -p 3000:3000 \
-e GOTENBERG_API_BASIC_AUTH_USERNAME=user \
-e GOTENBERG_API_BASIC_AUTH_PASSWORD=pass \
gotenberg/gotenberg:8.4.0 gotenberg --api-enable-basic-auth
To integrate this setup with Chromiumly, you need to update your configuration as outlined below:
GOTENBERG_ENDPOINT=http://localhost:3000
GOTENBERG_API_BASIC_AUTH_USERNAME=user
GOTENBERG_API_BASIC_AUTH_PASSWORD=pass
Or
{
"gotenberg": {
"endpoint": "http://localhost:3000",
"api": {
"basicAuth": {
"username": "user",
"password": "pass"
}
}
}
}
Or
Chromiumly.configure({
endpoint: "http://localhost:3000",
username: "user",
password: "pass",
});
API key authentication is primarily intended for the hosted Chromiumly API at https://api.chromiumly.dev. For setup and examples, see API Key Authentication (Hosted API). When both API key and basic auth are configured, the API key takes precedence.
To implement advanced authentication or add custom HTTP headers to your requests, you can use the customHttpHeaders option within the configure method. This allows you to pass additional headers, such as authentication tokens or custom metadata, with each API call.
For example, you can include a Bearer token for authentication along with a custom header as follows:
const token = await generateToken();
Chromiumly.configure({
endpoint: "http://localhost:3000",
customHttpHeaders: {
Authorization: `Bearer ${token}`,
"X-Custom-Header": "value",
},
});
Chromiumly wraps Gotenberg’s HTTP API: classes mirror the routes described in Gotenberg’s docs. Methods that take files accept a path string, Buffer, or ReadStream (e.g. html, header, footer, markdown).
The Templates class is the exception—it talks only to the Chromiumly hosted API and is documented below.
There are three different classes that come with a single method (i.e.convert) which calls one of
Chromium's conversion routes to convert html and markdown files, or
a url to a buffer which contains the converted PDF file content.
Similarly, a new set of classes have been added to harness the recently introduced Gotenberg screenshot routes. These classes include a single method called capture, which allows capturing full-page screenshots of html, markdown, and url.
import { UrlConverter } from "chromiumly";
const urlConverter = new UrlConverter();
const buffer = await urlConverter.convert({
url: "https://www.example.com/",
});
import { UrlScreenshot } from "chromiumly";
const screenshot = new UrlScreenshot();
const buffer = await screenshot.capture({
url: "https://www.example.com/",
});
The only requirement is that the file name should be index.html.
import { HtmlConverter } from "chromiumly";
const htmlConverter = new HtmlConverter();
const buffer = await htmlConverter.convert({
html: "path/to/index.html",
});
import { HtmlScreenshot } from "chromiumly";
const screenshot = new HtmlScreenshot();
const buffer = await screenshot.capture({
html: "path/to/index.html",
});
This route accepts an index.html file plus a markdown file.
import { MarkdownConverter } from "chromiumly";
const markdownConverter = new MarkdownConverter();
const buffer = await markdownConverter.convert({
html: "path/to/index.html",
markdown: "path/to/file.md",
});
import { MarkdownScreenshot } from "chromiumly";
const screenshot = new MarkdownScreenshot();
const buffer = await screenshot.capture({
html: "path/to/index.html",
markdown: "path/to/file.md",
});
Each convert() method takes an optional properties parameter of the following type which dictates how the PDF generated
file will look like.
type PageProperties = {
singlePage?: boolean; // Print the entire content in one single page (default false)
size?: {
width: number | string; // Paper width (number in inches or string with units: 72pt, 96px, 1in, 25.4mm, 2.54cm, 6pc, default 8.5)
height: number | string; // Paper height (number in inches or string with units: 72pt, 96px, 1in, 25.4mm, 2.54cm, 6pc, default 11)
};
margins?: {
top: number | string; // Top margin (number in inches or string with units: 72pt, 96px, 1in, 25.4mm, 2.54cm, 6pc, default 0.39)
bottom: number | string; // Bottom margin (number in inches or string with units: 72pt, 96px, 1in, 25.4mm, 2.54cm, 6pc, default 0.39)
left: number | string; // Left margin (number in inches or string with units: 72pt, 96px, 1in, 25.4mm, 2.54cm, 6pc, default 0.39)
right: number | string; // Right margin (number in inches or string with units: 72pt, 96px, 1in, 25.4mm, 2.54cm, 6pc, default 0.39)
};
preferCssPageSize?: boolean; // Define whether to prefer page size as defined by CSS (default false)
printBackground?: boolean; // Print the background graphics (default false)
omitBackground?: boolean; // Hide the default white background and allow generating PDFs with transparency (default false)
landscape?: boolean; // Set the paper orientation to landscape (default false)
scale?: number; // The scale of the page rendering (default 1.0)
nativePageRanges?: { from: number; to: number }; // Page ranges to print
};
Page Size and Margins Units
Both size and margins properties support two formats:
pt (points): e.g., "72pt"px (pixels): e.g., "96px"in (inches): e.g., "1in"mm (millimeters): e.g., "25.4mm"cm (centimeters): e.g., "2.54cm"pc (picas): e.g., "6pc"Examples:
// Using numeric values (inches)
properties: {
size: { width: 8.5, height: 11 },
margins: { top: 0.5, bottom: 0.5, left: 1, right: 1 }
}
// Using string values with units
properties: {
size: { width: "210mm", height: "297mm" }, // A4 size
margins: { top: "1cm", bottom: "1cm", left: "2cm", right: "2cm" }
}
// Mixing numeric and string values
properties: {
size: { width: 8.5, height: "11in" },
margins: { top: "10mm", bottom: 0.5, left: "72pt", right: 1 }
}
In addition to the PageProperties customization options, the convert() method also accepts a set of parameters to further enhance the versatility of the conversion process. Here's an overview of the full list of parameters:
```typescript type ConversionOptions = { properties?: PageProperties; // Customize the appearance of the generated PDF pdfFormat?: PdfFormat; // Define the PDF format for the conversion pdfUA?: boolean; // Enable PDF for Universal Access for optimal accessibility
$ claude mcp add chromiumly \
-- python -m otcore.mcp_server <graph>