Node.js · API

Image hosting API Node.js with built-in fetch.

Node 18+ has fetch and FormData built in. This snippet reads a file, posts multipart, and returns the hosted URL — no third-party dependencies.

Node.js
import fs from 'node:fs';

export async function uploadImage(filePath, apiKey) {
  const fd = new FormData();
  fd.append('file', new Blob([fs.readFileSync(filePath)]), filePath.split('/').pop());

  const headers = {};
  if (apiKey) headers.Authorization = `Bearer ${apiKey}`;

  const r = await fetch('https://imagetourl.cloud/api/upload', {
    method: 'POST',
    headers,
    body: fd,
  });

  const body = await r.json();
  if (!r.ok || body.error) throw new Error(body.error || `HTTP ${r.status}`);
  return body.data.url;
}

// Example
const url = await uploadImage('./screenshot.png', process.env.IMAGETOURL_KEY);
console.log(url); // https://imagetourl.cloud/uploads/abc123.png

Why use ImageToURL's API

Zero dependencies

Works with Node 18+'s global fetch and FormData. No axios, no form-data, no node-fetch. Fewer deps means fewer security patches to babysit.

Serverless-friendly

The same snippet runs in AWS Lambda, Cloudflare Workers, Vercel Edge Functions, and Deno Deploy without modification.

TypeScript-ready

Drop into a .ts file unchanged. The URL return type is string; error paths throw.

Streaming uploads

For large files, swap readFileSync for fs.createReadStream in a ReadableStream wrapper — memory-efficient for 50 MB+ uploads.

FAQ

Do I need node-fetch?

No — Node 18+ has global fetch. For older Node, npm install node-fetch@2 and require it. The API surface is identical.

What about Next.js server components?

Same code works in a Route Handler or server action. Cloudflare Pages, Vercel, and self-hosted Next.js all provide fetch globally.

Deno / Bun?

Identical. Deno has fetch and FormData built in; Bun matches Node.js's fetch API.

Can I upload a Buffer directly?

Yes: new Blob([buffer], { type: 'image/png' }) — then append to FormData. Useful when you already have image bytes in memory.

How do I upload a canvas in browser-side Node (Electron)?

canvas.toBlob(blob => uploadImage(blob)) — rename the function to accept a Blob instead of a path; the rest is identical.

Retry on 429?

Wrap the fetch in a small backoff loop. ImageToURL responds with Retry-After headers on rate limit — respect that value.

TypeScript types?

The response shape is { data: { url: string, id: string, size: number, mime: string, created_at: string } } | { error: string }. Declare as a union and narrow.

Express middleware for server-side uploads?

Accept multipart with multer, then re-POST the buffer to ImageToURL using the above function. Store the returned URL in your DB instead of local disk.