LifeAstroAPILifeAstroAPI

PDF reports (Node SDK)

Early access. The lifeastroapi Node package is being prepared for npm. Until it is published, ask us for early access; everything below describes the package as it ships.

The lifeastroapi/pdf subpath turns the JSON from client.reports.* into branded, print-ready PDFs — cover page, charts, planet and dasha tables, narrative sections — white-labelled with your logo, colours, footer and optional watermark.

The API itself returns JSON only. The PDF is built on your server, by this SDK. That keeps your branding and your customers' reports on your side, and it is why PDF rendering has requirements the rest of the SDK does not.

Two layers

LayerFunctionsNeeds
HTMLrender*Html(data, branding?)Nothing. Pure string functions with zero dependencies; run on Node, serverless, edge or in a browser.
PDF*Pdf(data, opts?), htmlToPdf(html, opts?)A headless Chromium, driven through Puppeteer (see below).

If you only call the API, or only need HTML, you can ignore everything about Puppeteer below — it is never loaded.

What you need for PDFs

Puppeteer is an optional peer dependency: it is not installed with lifeastroapi, and is imported only when you call a *Pdf function or htmlToPdf. Pick one of these setups.

SetupInstallDiskWhen to use
Puppeteer (simplest)npm install puppeteerroughly 400–500 MB — it downloads its own ChromeA normal server, VM or container.
puppeteer-core + your own Chromenpm install puppeteer-coreroughly 10–20 MB, plus the Chrome/Chromium you already haveChrome is already on the machine, or you install it from your OS package manager.
Serverlessnpm install puppeteer-core @sparticuz/chromiumsized to fit a Lambda layerAWS Lambda, Vercel functions and similar.

Also plan for:

  • Memory. Each render runs a Chromium page; allow a few hundred MB of RAM for the browser. Reuse one browser across requests rather than launching one per PDF (see Performance).
  • Fonts. See Fonts — without the right fonts, Hindi and other Indic text prints as empty boxes.
  • Puppeteer 24 or newer is recommended. The page footer uses a CSS page-margin box, which needs Chromium 131+; with an older browser the PDF still renders but the footer line is not printed.
  • Not available on runtimes that cannot run a browser (Cloudflare Workers, the browser itself). Use the HTML layer there and convert elsewhere.

Calling a *Pdf function without Puppeteer installed throws a clear error telling you to install it or pass your own.

Quick start

npm install lifeastroapi puppeteer
import { LifeAstro } from "lifeastroapi";
import { kundliDetailedPdf } from "lifeastroapi/pdf";
import { writeFileSync } from "node:fs";
 
const client = new LifeAstro({ apiKey: process.env.LIFEASTRO_API_KEY });
 
// 1. Fetch the report JSON
const report = await client.reports.kundliDetailed({
  date: "1990-01-15", time: "10:30", tz: "Asia/Kolkata", lat: 19.076, lon: 72.8777,
  name: "Arjun Mehta", place: "Mumbai, India", lang: "hi",
});
 
// 2. Render a branded PDF in one call
const pdf = await kundliDetailedPdf(report, {
  branding: {
    companyName: "Acme Astro",
    logoUrl: "https://cdn.acme.com/logo.png", // or a data: URI
    primaryColor: "#6b21a8",
    secondaryColor: "#9333ea",
    footerText: "© Acme Astro — astrology for everyone",
    watermarkText: "SAMPLE", // optional diagonal watermark
  },
});
writeFileSync("kundli.pdf", pdf);

Available reports

Each report has a render*Html and a *Pdf form:

ReportAPI methodHTMLPDF
Kundli (lite)reports.kundliLiterenderKundliLiteHtmlkundliLitePdf
Kundli (detailed)reports.kundliDetailedrenderKundliDetailedHtmlkundliDetailedPdf
Brihad Kundlireports.kundliBrihadrenderKundliBrihadHtmlkundliBrihadPdf
Match-makingreports.matchMakingrenderMatchMakingHtmlmatchMakingPdf
Mangal Doshareports.mangalDosharenderMangalDoshaHtmlmangalDoshaPdf
Dasha analysisreports.dashaAnalysisrenderDashaAnalysisHtmldashaAnalysisPdf
Numerologyreports.numerologyrenderNumerologyHtmlnumerologyPdf
Sade Satireports.sadeSatirenderSadeSatiHtmlsadeSatiPdf
Varshaphalreports.varshaphalrenderVarshaphalHtmlvarshaphalPdf
Horoscope (daily / weekly / monthly)reports.horoscopeDaily …renderHoroscopeHtmlhoroscopePdf

All render in en, hi and mr (and other locales where the report data carries them) — pass lang when you request the report.

Brihad Kundli is the large one (well over 100 pages). kundliBrihadPdf renders it twice so the table of contents shows real page numbers, adds a running header and footer, and writes PDF bookmarks. It is the slowest report to produce — give it a generous timeout and render it in a background job rather than inside a web request. For exact page numbers in the table of contents, also install the optional pdfjs-dist (npm install pdfjs-dist); without it the SDK falls back to an estimate.

Names and places on the cover

Pass name and place (or boyName / girlName / boyPlace / girlPlace for match-making) when you request the report. Without them the cover reads "Subject" / "Boy" / "Girl" and shows the birth coordinates.

const report = await client.reports.matchMaking({
  boy, girl, boyName: "Arjun", girlName: "Asha", boyPlace: "Mumbai", girlPlace: "Delhi",
});

place is display text only — the chart is always computed from lat / lon.

Branding

FieldEffect
companyNameShown on the cover.
logoUrlCover logo. http(s), data:image/... or a relative URL.
primaryColor / secondaryColorHeadings, table headers, accents.
footerTextLine printed in the bottom margin of every page.
watermarkTextOptional diagonal watermark.

Precedence: the branding you pass overrides the per-account branding embedded in the report JSON, which falls back to neutral defaults.

Performance

Launching Chromium for every PDF is slow. On a server, launch one browser and reuse it — the SDK will not close a browser you pass in:

import puppeteer from "puppeteer";
const browser = await puppeteer.launch();
const pdf = await kundliDetailedPdf(report, { branding, browser });
// ... reuse `browser` for later requests; call browser.close() on shutdown

Your own Chrome (puppeteer-core)

import puppeteer from "puppeteer-core";
const browser = await puppeteer.launch({
  executablePath: "/usr/bin/chromium", // macOS: "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
});
const pdf = await kundliLitePdf(report, { browser });

Or let the SDK launch it: kundliLitePdf(report, { puppeteer, launchOptions: { executablePath } }).

Serverless (AWS Lambda and similar)

import chromium from "@sparticuz/chromium";
import puppeteer from "puppeteer-core";
const browser = await puppeteer.launch({
  executablePath: await chromium.executablePath(),
  args: chromium.args,
});
const pdf = await horoscopePdf(report, { browser });

Serverless Chromium images ship without Indic fonts — bundle the Noto fonts you need with your function (see Fonts).

Docker / Linux servers

A minimal image that can render every report, including Hindi:

FROM node:22-slim
RUN apt-get update && apt-get install -y --no-install-recommends \
      chromium fonts-noto-core fonts-noto-extra \
    && rm -rf /var/lib/apt/lists/*
ENV PUPPETEER_SKIP_DOWNLOAD=true
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .

with puppeteer.launch({ executablePath: "/usr/bin/chromium", args: ["--no-sandbox"] }). --no-sandbox is needed when the container runs as root; prefer running as a non-root user and keeping the sandbox.

Fonts

The templates ask for the Noto Sans families. Chromium does not bundle fonts, so the machine that renders the PDF must have fonts covering the scripts you use. Without them, Devanagari and other Indic text prints as empty boxes.

  • Debian / Ubuntu: apt install fonts-noto-core (add fonts-noto-extra for the full set of Indic scripts)
  • macOS and Windows desktops already include Devanagari fonts.

Without Puppeteer

Bring your own renderer, or run where a browser is not available — the HTML layer has no dependencies:

import { renderMatchMakingHtml } from "lifeastroapi/pdf";
const html = renderMatchMakingHtml(matchReport, { primaryColor: "#b91c1c" });
// → your own Puppeteer/Playwright, Gotenberg, a print service, or the browser's Print dialog

The HTML is a complete, self-contained document with print CSS (A4, page margins, footer), so any Chromium-based converter gives the same layout. The Brihad table of contents, running header and bookmarks are added by kundliBrihadPdf and are not part of the plain HTML.

htmlToPdf options

All *Pdf functions accept these alongside branding:

OptionDefaultMeaning
browser—Reuse a launched browser. Not closed for you.
puppeteer—Inject the module (puppeteer-core).
launchOptions—Passed to puppeteer.launch() when the SDK launches the browser.
format"A4"A3, A5, Letter, Legal, Tabloid.
landscapefalseLandscape orientation.
printBackgroundtruePrint background colours.
margintemplate's{ top, bottom, left, right }, e.g. "10mm".
scale1Render scale, 0.1–2.
timeoutMs30000Time allowed for the page to load.

Security

Branding inputs are sanitized — colours are validated against a safe allowlist, the watermark and footer are CSS-escaped, and logoUrl is restricted to http(s), data:image/... and relative URLs. Chromium fetches logoUrl while rendering, so if you ever pass a logo URL supplied by an end user, run Puppeteer with restricted network egress to avoid requests to internal hosts (SSRF).

Troubleshooting

SymptomCause and fix
PDF rendering requires PuppeteerPuppeteer is not installed. npm install puppeteer, or pass { puppeteer } / { browser }.
Could not find Chromepuppeteer-core has no browser of its own — pass executablePath. With puppeteer, run npx puppeteer browsers install chrome.
Hindi text shows as boxesNo Indic font on the machine. Install Noto fonts (see Fonts).
Browser fails to launch in DockerMissing system libraries or the sandbox. Use the Dockerfile above.
No footer line on pagesThe browser is older than Chromium 131. Update Puppeteer.
Timeouts on Brihad KundliIt is a very large document rendered twice. Raise timeoutMs and render in a background job.
Cover says "Subject"Pass name (and place) when requesting the report.