Meme Generator API: Build Your Own Meme Platform

Meme Generator API: Build Your Own Meme Platform

I built a meme generator as a side project in 2018. It went viral on Product Hunt, crashed my server, and taught me that people really love making memes.

The technical part wasn't hard. Take an image, overlay text on top and bottom, return the meme. What surprised me was how much effort went into making text look right—the font, the stroke, the positioning. Get those details wrong and your memes look amateur.

Five years later, I rebuilt it with an image generation API. Same functionality, 80% less code, and it scaled to 50,000 memes per day without breaking a sweat.

Here's how to build a meme generator that actually works.

Why build a meme generatorWhy Build a Meme Generator?

Memes are internet currency. They're shareable, engaging, and drive massive traffic.

Common use cases:

  • Social media tools (let users create memes to share)
  • Marketing campaigns (branded meme generators for viral content)
  • Community platforms (meme creation as a feature)
  • Content creation tools (memes as part of a larger toolkit)
  • Educational tools (surprisingly, teachers use memes in lessons)

Building a meme generator from scratch means dealing with image manipulation, text rendering, font management, and performance optimization. Using an API handles all that complexity.

How meme generation worksHow Meme Generation Works

The concept is simple: background image + text overlay = meme.

The flow:

  1. User selects a meme template (or uploads their own)
  2. User enters top text and bottom text
  3. API renders the image with text overlaid
  4. Return the meme to download or share

The complexity is in rendering text properly. Professional memes have:

  • Bold, readable fonts (usually Impact)
  • White text with black stroke (readable on any background)
  • Centered alignment
  • Proper spacing and sizing
  • Text that doesn't overflow or look cramped

Different meme templates need different layouts.

Topbottom text memes classicTop/Bottom Text Memes (Classic)

The original meme format. Text at the top, text at the bottom, image in the middle.

Examples:

  • Distracted Boyfriend
  • Drake Hotline Bling
  • Two Buttons
  • Always Has Been

Template structure:

  • Top text area (centered, large font)
  • Image content in middle
  • Bottom text area (centered, large font)

Single caption memesSingle Caption Memes

Modern memes often use just one caption, usually at the bottom.

Examples:

  • This Is Fine
  • Woman Yelling at Cat
  • Is This a Pigeon?

Template structure:

  • Full image
  • Single text area (top or bottom, depending on template)

Multi panel memesMulti-Panel Memes

Memes with multiple frames telling a story.

Examples:

  • Brain Meme (expanding brain)
  • Gru's Plan (4-panel)
  • Surprised Pikachu

Template structure:

  • Multiple image sections
  • Text areas specific to each panel
  • Sometimes text inside panels, sometimes captions below

Label memesLabel Memes

Templates where you label different parts of the image.

Examples:

  • Spider-Man Pointing (labels on each Spider-Man)
  • Galaxy Brain (labels on each brain level)
  • Expanding Brain (similar)

Template structure:

  • Multiple small text areas positioned on specific image elements

How to build a meme generatorHow to Build a Meme Generator

The technical implementation is straightforward with an API.

Step 1 create meme templatesStep 1: Create Meme Templates

Design templates for popular meme formats. Each template defines the background image and editable text areas.

For classic top/bottom memes, your template needs:

  • Background image
  • Top text field (large, white, black stroke)
  • Bottom text field (large, white, black stroke)

In Imejis.io, upload the meme background and add two text layers positioned at top and bottom. Mark them as editable so the API can change them.

Step 2 build the user interfaceStep 2: Build the User Interface

Create a simple form where users enter their meme text.

<form id="meme-generator">
  <select id="template">
    <option value="distracted-boyfriend">Distracted Boyfriend</option>
    <option value="drake">Drake Hotline Bling</option>
    <option value="two-buttons">Two Buttons</option>
  </select>
 
  <input type="text" id="top-text" placeholder="Top text" maxlength="100" />
  <input
    type="text"
    id="bottom-text"
    placeholder="Bottom text"
    maxlength="100"
  />
 
  <button type="submit">Generate Meme</button>
</form>
 
<div id="meme-result">
  <!-- Generated meme appears here -->
</div>

Step 3 call the api to generate memesStep 3: Call the API to Generate Memes

When the user submits, send their text to the API and display the generated meme.

document
  .getElementById("meme-generator")
  .addEventListener("submit", async (e) => {
    e.preventDefault()
 
    const template = document.getElementById("template").value
    const topText = document.getElementById("top-text").value
    const bottomText = document.getElementById("bottom-text").value
 
    const meme = await generateMeme(template, topText, bottomText)
 
    // Display the meme
    document.getElementById(
      "meme-result"
    ).innerHTML = `<img src="${meme.url}" alt="Generated meme" />
     <a href="${meme.url}" download>Download Meme</a>`
  })
 
async function generateMeme(template, topText, bottomText) {
  const templateIds = {
    "distracted-boyfriend": "TEMPLATE_ID_1",
    drake: "TEMPLATE_ID_2",
    "two-buttons": "TEMPLATE_ID_3",
  }
 
  const response = await fetch(
    `https://render.imejis.io/v1/${templateIds[template]}`,
    {
      method: "POST",
      headers: {
        Authorization: "Bearer YOUR_API_KEY",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        top_text: topText.toUpperCase(), // Classic memes use uppercase
        bottom_text: bottomText.toUpperCase(),
      }),
    }
  )
 
  const blob = await response.blob()
  const url = URL.createObjectURL(blob)
 
  return { url }
}

Complete code examplesComplete Code Examples

Here's how to build a meme generator in different environments.

React meme generatorReact Meme Generator

import React, { useState } from "react"
import axios from "axios"
 
function MemeGenerator() {
  const [template, setTemplate] = useState("distracted-boyfriend")
  const [topText, setTopText] = useState("")
  const [bottomText, setBottomText] = useState("")
  const [memeUrl, setMemeUrl] = useState(null)
  const [loading, setLoading] = useState(false)
 
  const templates = {
    "distracted-boyfriend": "TEMPLATE_ID_1",
    drake: "TEMPLATE_ID_2",
    "two-buttons": "TEMPLATE_ID_3",
  }
 
  const generateMeme = async () => {
    setLoading(true)
 
    try {
      const response = await axios({
        method: "post",
        url: `https://render.imejis.io/v1/${templates[template]}`,
        headers: {
          Authorization: "Bearer YOUR_API_KEY",
          "Content-Type": "application/json",
        },
        data: {
          top_text: topText.toUpperCase(),
          bottom_text: bottomText.toUpperCase(),
        },
        responseType: "blob",
      })
 
      const url = URL.createObjectURL(response.data)
      setMemeUrl(url)
    } catch (error) {
      console.error("Error generating meme:", error)
      alert("Failed to generate meme. Please try again.")
    } finally {
      setLoading(false)
    }
  }
 
  return (
    <div className="meme-generator">
      <h1>Meme Generator</h1>
 
      <div className="controls">
        <select value={template} onChange={(e) => setTemplate(e.target.value)}>
          <option value="distracted-boyfriend">Distracted Boyfriend</option>
          <option value="drake">Drake Hotline Bling</option>
          <option value="two-buttons">Two Buttons</option>
        </select>
 
        <input
          type="text"
          placeholder="Top text"
          value={topText}
          onChange={(e) => setTopText(e.target.value)}
          maxLength={100}
        />
 
        <input
          type="text"
          placeholder="Bottom text"
          value={bottomText}
          onChange={(e) => setBottomText(e.target.value)}
          maxLength={100}
        />
 
        <button onClick={generateMeme} disabled={loading}>
          {loading ? "Generating..." : "Generate Meme"}
        </button>
      </div>
 
      {memeUrl && (
        <div className="meme-result">
          <img src={memeUrl} alt="Generated meme" />
          <a href={memeUrl} download="meme.png">
            Download Meme
          </a>
          <button
            onClick={() =>
              navigator.share({ files: [new File([memeUrl], "meme.png")] })
            }
          >
            Share Meme
          </button>
        </div>
      )}
    </div>
  )
}
 
export default MemeGenerator

Python flask backendPython Flask Backend

from flask import Flask, request, jsonify, send_file
import requests
import io
 
app = Flask(__name__)
 
TEMPLATES = {
    'distracted-boyfriend': 'TEMPLATE_ID_1',
    'drake': 'TEMPLATE_ID_2',
    'two-buttons': 'TEMPLATE_ID_3'
}
 
@app.route('/generate-meme', methods=['POST'])
def generate_meme():
    data = request.json
 
    template = data.get('template', 'distracted-boyfriend')
    top_text = data.get('top_text', '').upper()
    bottom_text = data.get('bottom_text', '').upper()
 
    # Validate input
    if not top_text and not bottom_text:
        return jsonify({'error': 'Please provide at least one text field'}), 400
 
    # Generate meme
    template_id = TEMPLATES.get(template)
 
    response = requests.post(
        f'https://render.imejis.io/v1/{template_id}',
        headers={
            'Authorization': 'Bearer YOUR_API_KEY',
            'Content-Type': 'application/json'
        },
        json={
            'top_text': top_text,
            'bottom_text': bottom_text
        }
    )
 
    if response.status_code == 200:
        # Return image directly
        return send_file(
            io.BytesIO(response.content),
            mimetype='image/png',
            as_attachment=True,
            download_name='meme.png'
        )
    else:
        return jsonify({'error': 'Failed to generate meme'}), 500
 
@app.route('/templates', methods=['GET'])
def list_templates():
    return jsonify({
        'templates': [
            {'id': 'distracted-boyfriend', 'name': 'Distracted Boyfriend'},
            {'id': 'drake', 'name': 'Drake Hotline Bling'},
            {'id': 'two-buttons', 'name': 'Two Buttons'}
        ]
    })
 
if __name__ == '__main__':
    app.run(debug=True)

Nodejs express apiNode.js + Express API

const express = require("express")
const axios = require("axios")
const app = express()
 
app.use(express.json())
 
const TEMPLATES = {
  "distracted-boyfriend": "TEMPLATE_ID_1",
  drake: "TEMPLATE_ID_2",
  "two-buttons": "TEMPLATE_ID_3",
}
 
app.post("/api/generate-meme", async (req, res) => {
  const { template, topText, bottomText } = req.body
 
  // Validate input
  if (!topText && !bottomText) {
    return res
      .status(400)
      .json({ error: "Please provide at least one text field" })
  }
 
  const templateId = TEMPLATES[template] || TEMPLATES["distracted-boyfriend"]
 
  try {
    const response = await axios({
      method: "post",
      url: `https://render.imejis.io/v1/${templateId}`,
      headers: {
        Authorization: "Bearer YOUR_API_KEY",
        "Content-Type": "application/json",
      },
      data: {
        top_text: topText.toUpperCase(),
        bottom_text: bottomText.toUpperCase(),
      },
      responseType: "arraybuffer",
    })
 
    // Return image
    res.set("Content-Type", "image/png")
    res.send(response.data)
  } catch (error) {
    console.error("Error generating meme:", error)
    res.status(500).json({ error: "Failed to generate meme" })
  }
})
 
app.get("/api/templates", (req, res) => {
  res.json({
    templates: [
      { id: "distracted-boyfriend", name: "Distracted Boyfriend" },
      { id: "drake", name: "Drake Hotline Bling" },
      { id: "two-buttons", name: "Two Buttons" },
    ],
  })
})
 
app.listen(3000, () => {
  console.log("Meme generator API running on port 3000")
})

Advanced featuresAdvanced Features

Take your meme generator beyond basic top/bottom text.

User uploaded imagesUser-Uploaded Images

Let users upload their own images as meme backgrounds.

async function uploadAndCreateMeme(imageFile, topText, bottomText) {
  // Upload image to your storage
  const formData = new FormData()
  formData.append("image", imageFile)
 
  const uploadResponse = await fetch("/api/upload-image", {
    method: "POST",
    body: formData,
  })
 
  const { imageUrl } = await uploadResponse.json()
 
  // Generate meme with uploaded image
  const response = await fetch(
    "https://render.imejis.io/v1/CUSTOM_TEMPLATE_ID",
    {
      method: "POST",
      headers: {
        Authorization: "Bearer YOUR_API_KEY",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        background_image: imageUrl,
        top_text: topText.toUpperCase(),
        bottom_text: bottomText.toUpperCase(),
      }),
    }
  )
 
  return response.blob()
}

Text customizationText Customization

Let users customize font size, color, and position.

{
  top_text: "When you finally fix the bug",
  bottom_text: "But introduce two more",
  text_size: 48,
  text_color: "#FFFFFF",
  stroke_color: "#000000",
  stroke_width: 2,
  text_align: "center"
}

Store generated memes and display a gallery of recent or popular memes.

// Save meme to database after generation
await saveMeme({
  template: template,
  topText: topText,
  bottomText: bottomText,
  imageUrl: memeUrl,
  createdBy: userId,
  likes: 0,
})
 
// Display gallery
const recentMemes = await getRecentMemes(20)

Social sharingSocial Sharing

Add one-click sharing to social media platforms.

// Web Share API
async function shareMeme(memeUrl) {
  if (navigator.share) {
    try {
      const response = await fetch(memeUrl)
      const blob = await response.blob()
      const file = new File([blob], "meme.png", { type: "image/png" })
 
      await navigator.share({
        title: "Check out this meme!",
        files: [file],
      })
    } catch (error) {
      console.error("Error sharing:", error)
    }
  } else {
    // Fallback: copy link or open share dialog
    copyToClipboard(memeUrl)
  }
}

Ai generated captionsAI-Generated Captions

Use AI to suggest funny captions based on the template.

async function suggestCaptions(template) {
  // Call AI API (OpenAI, Claude, etc.)
  const response = await fetch("/api/suggest-captions", {
    method: "POST",
    body: JSON.stringify({ template }),
  })
 
  const { suggestions } = await response.json()
 
  // Display suggestions to user
  return suggestions
}

Template design best practicesTemplate Design Best Practices

Good meme templates make text readable and positioning easy.

Classic impact font styleClassic Impact Font Style

The standard meme text style:

  • Font: Impact or Arial Black
  • Color: White (#FFFFFF)
  • Stroke: Black (#000000), 2-4px width
  • Transform: Uppercase
  • Alignment: Center

This works on any background because of the black stroke.

Text positioningText Positioning

Leave enough space for text without covering important image elements.

Top text area:

  • 10-15% from the top
  • Centered horizontally
  • Large enough for 2 lines if needed

Bottom text area:

  • 10-15% from the bottom
  • Centered horizontally
  • Large enough for 2 lines if needed

Handle text overflowHandle Text Overflow

Users will try to write novels. Plan for it.

Solutions:

  • Set character limits (100 characters per text field)
  • Auto-size text (shrink font if text is long)
  • Wrap text to multiple lines (max 2-3 lines)
  • Truncate with ellipsis if really needed

Test your templates with the longest realistic captions before launching.

Mobile optimizationMobile Optimization

Most memes are created and viewed on mobile.

  • Readable at small sizes (600x600px minimum)
  • Touch-friendly UI elements
  • Fast image loading
  • Easy sharing to social apps

Content moderationContent Moderation

Public meme generators attract trolls. Plan for moderation.

Text filteringText Filtering

Filter inappropriate text before generation.

const bannedWords = ['offensive', 'words', 'here'];
 
function moderateText(text) {
  const lowerText = text.toLowerCase();
 
  for (const word of bannedWords) {
    if (lowerText.includes(word)) {
      return false; // Reject
    }
  }
 
  return true; // Allow
}
 
// Before generating
if (!moderateText(topText) || !moderateText(bottomText)) {
  return res.status(400).json({ error: 'Inappropriate content detected' });
}

Image moderationImage Moderation

If users upload images, moderate them before processing.

Use image moderation APIs (AWS Rekognition, Google Cloud Vision, or dedicated services) to detect inappropriate content.

Rate limitingRate Limiting

Prevent abuse with rate limits.

const rateLimit = require("express-rate-limit")
 
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 20, // Max 20 memes per 15 minutes
  message: "Too many memes created. Please try again later.",
})
 
app.use("/api/generate-meme", limiter)

Monetization ideasMonetization Ideas

Turn your meme generator into a business.

Freemium modelFreemium Model

  • Free tier: Generate memes with watermark
  • Paid tier: Watermark-free memes, more templates, higher resolution

Template marketplaceTemplate Marketplace

Sell premium meme templates to power users.

White label solutionWhite-Label Solution

License your meme generator to brands for their campaigns.

Api accessAPI Access

Offer API access to developers building apps that need meme generation.

AdvertisingAdvertising

Show ads on your meme generator site. Meme platforms get high traffic and engagement.

FaqFAQ

Can i use copyrighted images for memesCan I use copyrighted images for memes?

Legally risky. Most popular meme images exist in a gray area. For commercial platforms, use public domain images, Creative Commons content, or create original templates. The API itself is just a tool—you're responsible for image rights.

How do i handle text wrapping for long captionsHow do I handle text wrapping for long captions?

Design templates with auto-sizing text or set character limits. Most meme generators limit top text to 100 characters, bottom text to 100 characters. Test with your longest realistic input before launching.

Whats the best font for meme textWhat's the best font for meme text?

Impact font is the classic meme standard. Bold, white text with black stroke (outline). It's readable over any background. Most meme generators also offer Arial Black or Anton as alternatives for different meme styles.

Can users upload their own imagesCan users upload their own images?

Yes. Accept image uploads, store them temporarily or in your CDN, then use that URL as the background in your meme template. Remember to moderate uploads if this is a public platform to avoid inappropriate content.

How do i prevent abuse of a public meme generatorHow do I prevent abuse of a public meme generator?

Rate limit API calls per user or IP. Add content moderation for text (filter profanity, hate speech). Consider requiring sign-in for generation. Monitor usage patterns and block bad actors. Most meme platforms use a combination of these methods.

Build the next viral meme platformBuild the Next Viral Meme Platform

Memes drive massive engagement. Every successful social platform has meme generation or sharing at its core.

Building a meme generator from scratch means dealing with image processing, text rendering, font management, and infrastructure scaling. Using an image generation API lets you focus on the user experience and go viral faster.

Design great templates, build a simple interface, connect to the API, and watch people create millions of memes. The technical part is the easy part now.

Get started with Imejis.io →