Learn how to build simple Image API service

shriji profile image Shriji ・3 min read

This weekend I built https://biriyani.anoram.com/ Biriyani As A Service (BaaS) as a parody for Backend-As-A-Service. A Simple replica of several other image placeholders, floof placeholders(Dog, cat, Goat...), etc,.

Biryani (noun): an Indian dish made with highly seasoned rice and meat, fish, or vegetables. Indian orders 95~200 Biriyanis Per Minute (BPM).



  1/ NodeJS.
  2/ Polka, CORS, compression, sirv
  3/ Images for the service
  4/ Svelte starter template (https://svelte.dev/) for front-end

Since Express is overused I explored the alternative Polka and Sirv. Both of them achieve the same result. This tutorial will cover the process of how I built the best in class BaaS 😝.

Let's get the images first

I used images-scraper. A simple library that gets you images with interesting accuracy for noncommercial reuse.

const google = new Scraper({
    puppeteer: {
        headless: true,
        detail: false,
    tbs: {
        isz: "l",
        sur: "f"

I ran with these options. Although if you are sure that you want to use your own images then you can skip this step. But remember to have them named numerically (will cover it later in the steps).

Polka base setup to see if it works. Get polka from here.

const polka = require('polka');


  .get('/', (req, res) => {
    console.log(`User hit`);
    res.end(`Hello World`);
  .listen(3000, err => {
    if (err) throw err;
    console.log(`> Running on localhost:3000`);

Now that Polka begins working we can play with it. We need to send a JSON response to the end users or ones who integrate in their apps.

 .get('/get', (req, res) => {
        let data = {
            "image": `image.jpg`,
        send(res, 200, data);

When visiting http://localhost:3000/get you will get


Now we need to send random image from the set of images that is obtained from step 1. I keep a local copy so it is much easier, I downloaded using jDownloader and renamed them from 1 - 21 also made sure the extension is jpg and is lowercase. At this point of time I have also added cors for all routes so that the traffic can come from anywhere and not result in Access-Control issues when using in the front-end apps.

Service static files using polka?

Well by choice it is bad nginx does a better job for that but for a hobby weekend project it's cool. For serving static assets I put them in public directory. I used this example from polka

Now the code block becomes like this

const baseURL = "https://biriyani.anoram.com/img/" 
//you need to change this if you are planning to host yourself

    .use(compress, assets)
    .get('/get', (req, res) => {
        let biriyanis = 22
        const randombiriyani = Math.floor(Math.random() * (biriyanis - 1) + 1);
        let data = {
            "image": `${baseURL}${randombiriyani}.jpg`,
        send(res, 200, data);
    .listen(333, err => {
        if (err) throw err;
        console.log(`> Running on http://localhost:333`);

And my public directory tree looks like this so if anyone hits / it will show index.html from public directory

β”‚   β”‚   index.html
β”‚   β”‚   build #assets
β”‚   β”‚   
β”‚   └───img
β”‚       β”‚   1.jpg
β”‚       β”‚   2.jpg
β”‚       β”‚   ...

I used svelte for the front-end that hits the API and places the image.

    const url = "https://biriyani.anoram.com/get";
    let biriyani;
    let result;
    async function fetchImg() {
        const response = await fetch(url)
        result = await response.json()
        biriyani = result.image;


This should give you the idea of how to build an API service that does something like this.

Other parts are just eye candy and basic css, its on the repo.

So now it begins to work but it must be protected. There could be an abusive use of the API and it should be rate limited express-slow-down helps you do that.

const ratelimit = slowDown({
    windowMs: 15 * 60 * 1000, // 15 minutes
    delayAfter: 5, // allow 5 requests to go at full-speed, then...
    delayMs: 100 // 6th request has a 100ms delay, 7th has a 200ms delay, 8th gets 300ms, etc.

   .use("trust proxy")
   .use(ratelimit) //this should also be added

A month ago I built On demand HTTP Codes with images. I had plenty fun building it so much so I added easter eggs to the project one of it is posted here.

Here is the repo.


Posted on by:

shriji profile



Co-Founder @anoram. High Performance JavaScript Apps. I created https://vadivelu.anoram.com/ and https://biriyani.anoram.com/ API.


markdown guide