3 min read

Using Bannerbear in a Batch Generation Process

Need to batch-generate lots of social media images for a website you run

by Jon Yongfook · June 2020
Using Bannerbear in a Batch Generation Process
Using Bannerbear in a Batch Generation Process


    Need to batch-generate lots of social media images for a website you run? Here's an example of using Bannerbear in a command-line script that you can run anytime.

    A common use-case for Bannerbear is generating bespoke og:image and twitter card images for every page on your website. When automated, this is a simple and zero maintenance way to drive more traffic to your pages from social media.

    There are various ways to implement this in your projects using Bannerbear. Since Bannerbear is a REST API, one popular method is employing an event-driven approach, pinging Bannerbear whenever your platform generates new content.

    But another method would be a batch approach, where you auto generate images in large batches at once and save them to your own filesystem.

    Advantages of Batch Generation

    • Zero brittleness as the images are pre-generated
    • Simple to manage expiry / regeneration; just delete the images and rerun the script
    • Keeps image generation code separate from your core

    Disadvantages of Batch Generation

    • You have to "remember" to run the script*
    • Less suitable when there is new content being published constantly

    *could easily be automated though!

    Batch generation is ideal for sites that are built via a static site generator where you want static image assets and no code running on-the-fly.

    The Bannerbear marketing site (this website) is run on a static site generator called Middleman and all the social media og:image files are generated by batch using a Rakefile. Whenever I add new content to the site I simply run:

    rake bannerbear:generate

    Which runs the following process:

    • Fetch a json feed of all pages of the site
    • Then, for each pageā€¦
    • Checks for a pre-existing og:image in a specified folder
    • If the image file already exists, move on
    • If the image file doesn't exist, send a request to Bannerbear
    • Wait for the image to get generated, then save it to the specified folder
    • Move to the next page in the json feed

    And that's it! This is written in Ruby since that's what I know best, but you could write something similar to this in any programming language :)

    View this Gist on Github

    require 'httparty'
    require 'open-uri'
    namespace :bannerbear do
      task :generate do
        puts "Starting json request"
        response = HTTParty.get(ENV['LOCAL_BB_SITE_ALL_POSTS'])
          json = JSON.parse response.body
          puts "Number of pages: #{json.size}"
          json.each_with_index do |page,i|
            puts "#{i} ---------------------------------------"
            puts "Checking file exists for"
            path = './source/images/opengraph/' + page['filename']
            puts path
            if !File.file?(path)
              puts "File doesn't exist, lets create!"
              general_template_id = ENV['BB_SITE_GENERAL_OG_TEMPLATE']
              blog_template_id = ENV['BB_SITE_BLOG_OG_TEMPLATE']
              template = general_template_id
              mods = [
                  :name => "title",
                  :text => page['title']
              if page['blog_date']
                template = blog_template_id
                mods = [
                    :name => "title",
                    :text => page['title']
                    :name => "date",
                    :text => page['blog_date']
              payload = {
                :template => template,
                :modifications => mods,
              puts "Creating Bannerbear API request"
              puts payload
              response = HTTParty.post("https://api.bannerbear.com/v2/images", {
                body: payload,
                headers: {"Authorization" => "Bearer #{ENV['BANNERBEAR_SOCIAL_MEDIA_PROJECT_API_KEY']}"}
              image_json = JSON.parse response.body
              counter = 1
              #poll for image to complete
              5.times do |attempt|
                puts "Attempt #{attempt}"
                counter = counter+1
                response = HTTParty.get(image_json['self'], {
                  headers: {"Authorization" => "Bearer #{ENV['BANNERBEAR_SOCIAL_MEDIA_PROJECT_API_KEY']}"}
                image_json = JSON.parse response.body
                if image_json['image_url_png']
                  puts "Image generated!"
                  puts image_json['image_url_png']
                  download = open(image_json['image_url_png'])
                  IO.copy_stream(download, path)
                sleep 1
            puts "Moving to next page..."
        rescue => e
          puts "Rescued #{e.inspect}"

    View this Gist on Github

    Jon Yongfook@yongfook
    Jon is the founder of Bannerbear. He has worked as a designer and programmer for 20 years and is fascinated by the role of technology in design automation.

    Follow the Journey

    Hello I'm Jon, the founder of Bannerbear — every 2 weeks I send a newsletter with updates from the Product, Marketing and Business sides of my startup, subscribe below to receive it!