Skip to Content
GuidesImplement snapshots server

Implement snapshots server

Wire chart screenshots to your backend so takeScreenshot() (and the top-bar camera) can upload a PNG and return a public image URL.

How uploads work

  1. The SDK captures the chart (takeClientScreenshot / built-in camera).
  2. For hosted uploads it calls either:
  • image_storage_adapter.upload(blob) (preferred when set), or
  • POST to construct-time snapshot_url with multipart field preparedImage (PNG).
  1. The response must yield an image URL (plain text body, or JSON with url / imageUrl / similar).
  2. The widget emits onScreenshotReady with that URL.
const chart = GoChartingSDK.createChart("#chart", { datafeed: myDatafeed, symbol: "NASDAQ:AAPL", interval: "1D", licenseKey: "YOUR_LICENSE_KEY", snapshot_url: "https://your.api/snapshots", onReady: () => { chart.subscribe("onScreenshotReady", (imageUrl) => { console.log("Uploaded:", imageUrl); }); }, }); // Later: const imageUrl = await chart.takeScreenshot();

Option A — snapshot_url (HTTP endpoint)

Client

snapshot_url: "https://api.example.com/snapshots",

Request contract

ItemValue
MethodPOST
Bodymultipart/form-data
File fieldpreparedImage (PNG, filename like chart.png / snapshot.png)
CredentialsOmitted by the SDK (credentials: "omit" on the fetch path)

Response contract

Return the public URL of the stored image:

  • Plain text — body is the URL string (optional surrounding quotes are stripped).
  • JSON — object with a string field such as url, imageUrl, src, or location.

Examples:

https://cdn.example.com/snaps/abc123.png
{ "url": "https://cdn.example.com/snaps/abc123.png" }

Non-2xx responses cause takeScreenshot() to reject.

Minimal Node server

import express from "express"; import multer from "multer"; import { randomUUID } from "crypto"; import { writeFile } from "fs/promises"; import path from "path"; const app = express(); const upload = multer({ storage: multer.memoryStorage() }); const PUBLIC_BASE = "https://cdn.example.com/snaps"; app.post("/snapshots", upload.single("preparedImage"), async (req, res) => { if (!req.file) { return res.status(400).send("missing preparedImage"); } const id = randomUUID(); const fileName = `${id}.png`; await writeFile(path.join("/var/www/snaps", fileName), req.file.buffer); // Plain-text URL (also valid: res.json({ url: ... })) res.type("text/plain").send(`${PUBLIC_BASE}/${fileName}`); }); app.listen(3001);

Point the chart at that route:

snapshot_url: "https://api.example.com/snapshots",

Serve the saved files from your CDN or static host so the returned URL is reachable in the browser.

Option B — image_storage_adapter (preferred)

When both are set, image_storage_adapter.upload wins over snapshot_url. Use this to call S3, GCS, or your own SDK without a fixed multipart URL.

const chart = GoChartingSDK.createChart("#chart", { datafeed: myDatafeed, symbol: "NASDAQ:AAPL", interval: "1D", licenseKey: "YOUR_LICENSE_KEY", image_storage_adapter: { async upload(blob) { const form = new FormData(); form.append("file", blob, "chart.png"); const res = await fetch("https://api.example.com/upload", { method: "POST", body: form, headers: { Authorization: `Bearer ${token}` }, }); if (!res.ok) throw new Error("upload failed"); const { url } = await res.json(); return url; // must be a non-empty string }, }, });

Local-only capture (no server)

If you only need a canvas or data URL in the page:

const canvas = await chart.takeClientScreenshot(); const dataUrl = canvas.toDataURL("image/png");

takeClientScreenshot does not call snapshot_url or the image adapter.

Top-bar camera

The built-in screenshot control uses the same upload path when configured. Hide it with exclude options if you only want programmatic capture — see Configuration and Chart API exclude.screenshot.

Checklist

  • Endpoint accepts POST multipart with field preparedImage
  • Response is a reachable HTTPS image URL (text or JSON)
  • CORS allows your chart origin if the upload host differs
  • Prefer image_storage_adapter when you need auth headers or custom storage
  • Subscribe to onScreenshotReady and/or await chart.takeScreenshot()
  • Chart APItakeScreenshot, takeClientScreenshot, onScreenshotReady
  • Configurationsnapshot_url, image_storage_adapter
Last updated on