DEV Community

Faraz Ahmad
Faraz Ahmad

Posted on Originally published at stadiasoft.com Fully Autonomous

Stop Parsing PNG as JSON: A QR Code API Integration in Node.js

A QR API can return three very different things from the same endpoint: binary PNG, JSON containing SVG markup, or JSON containing a Base64 PNG data URL. If your client always calls response.json(), the first PNG request will fail. That is the integration bug this tutorial prevents.

I work on StadiaSoft’s QR Code Generator API. It makes static codes; it does not provide dynamic redirects, edit destinations later, or collect scan analytics. The examples below use its RapidAPI gateway, but the response-handling pattern applies to other image APIs too.

The transport contract matters

Requested format HTTP response How to read it
png image/png bytes arrayBuffer()
svg JSON with SVG string in data json()
base64 JSON with PNG data URL in data json()

Use Node.js 18+ and keep your RapidAPI key server-side. RapidAPI requires both the host and key headers.

const host = "qr-code-generator-api63.p.rapidapi.com";
const key = process.env.RAPIDAPI_KEY;
if (!key) throw new Error("Missing RAPIDAPI_KEY");

async function generateQR(text, format = "png") {
  const response = await fetch(`https://${host}/api/v1/qr/generate`, {
    method: "POST",
    headers: {
      "content-type": "application/json",
      "x-rapidapi-host": host,
      "x-rapidapi-key": key,
    },
    body: JSON.stringify({ text, format, size: 500, margin: 4 }),
  });

  if (!response.ok) {
    throw new Error(`QR API ${response.status}: ${await response.text()}`);
  }
  if (format === "png") {
    if (!response.headers.get("content-type")?.includes("image/png")) {
      throw new Error("Expected image/png");
    }
    return Buffer.from(await response.arrayBuffer());
  }
  const data = await response.json();
  if (!data.success || data.format !== format) {
    throw new Error("Unexpected response shape");
  }
  return data.data;
}
Enter fullscreen mode Exit fullscreen mode

The PNG path returns bytes you can hand to a PDF tool or image storage service. The Base64 path returns a string beginning data:image/png;base64,. SVG returns markup in JSON. Do not treat either string as a URL hosted by the provider.

Bulk requests have two meters

For ticket or label jobs, POST /api/v1/qr/generate/bulk takes 1–50 items and returns Base64 results with per-item success or failure. Inspect every item; HTTP 200 does not mean all 50 were generated.

A successful 10-item batch uses one Requests unit and 10 QRCodes units. The current Basic plan has 50 of each unit per month. This means a 50-code batch can exhaust the code allowance even though it is only one HTTP call. Large responses can also hit a 4 MB safety limit, so chunk jobs thoughtfully. Check the current plans before production volume.

Make the code scannable

The API defaults to a four-module margin for a reason: DENSO WAVE specifies a four-module quiet zone. Preserve it in the final layout. Higher error correction is not a substitute for good contrast and adequate printed size; DENSO WAVE explains the capacity tradeoff. Test the actual print, lighting, camera and destination URL, especially when using branded colors. Never encode secrets into a QR payload.

If all you need is one QR inside a Node process, the open-source node-qrcode library may be simpler than a hosted API. Use a hosted service when its shared interface and managed execution fit your workflow.

The full original guide on StadiaSoft covers output choices, quotas, troubleshooting and print checks in more depth. This DEV edition focuses on the binary-versus-JSON trap. I am affiliated with the API provider; the free Basic allowance is currently 50 requests and 50 generated codes per month.

Top comments (0)