NodeJS PhantomJS screenshot via Express

In my first blog post about NodeJS, I thought it would neat to utilize PhantomJS to fetch a URL, take a screenshot, and serve it back to the user as a static asset.

Install NodeJS & PhantomJS via brew, if you haven't already:

brew install node
brew install phantomjs

Create a new directory, and define a new file: package.json, contents:

  "name": "phantomjs_screenshot",
  "description": "phantomjs screeshot",
  "version": "0.0.1",
  "private": true,
  "dependencies": {
    "express": "3.x",
    "phantom": "*",
    "jade": "*"

Install dependencies:

npm install

I used Express to handle the routes and serve static assets, and Jade as the HTML middleware.

I create a views subdirectory for Jade with a new layout, file: views/layout.jade

doctype html
    title #{title}
      h1 #{title}
      block content

And another view file for the index page, which creates a form with an input element for URL. file: views/index.jade.

extend layout
block content
  form(name="process_url", action="/process_url", method="post")
    input(type="text", name="url")
    input(type="submit", value="Submit")

I then created the main app file "app.js" to run the server.

var express = require('express');
var app = express();

// define the public directory for static assets
var public_dir = __dirname + '/public';

// setup express

// setup jade
app.set('views', __dirname + '/views')
app.set('view engine', 'jade')

// route: get: /
app.get('/', function (req, res) {
    { title : 'NodeJS PhantomJS Screenshot' }

// route: post: /process_url'/process_url', function (req, res) {

  // get url to process
  var url_to_process = req.body.url;
  if (url_to_process === undefined || url_to_process == '') {
    res.writeHead(404, {'Content-Type': 'text/plain'});
    res.end("404 Not Found");

  // phantomjs screenshot
  var phantom = require('phantom');
    ph.createPage(function(page){, function(status){
        if (status == "success") {
          // put images in public directory
          var image_file_name = url_to_process.replace(/\W/g, '_') + ".png"
          var image_path = public_dir + "/" + image_file_name
          page.render(image_path, function(){
            // redirect to static image
        else {
          res.writeHead(404, {'Content-Type': 'text/plain'});
          res.end("404 Not Found");


// start server
var server = app.listen(3000, function() {
  console.log('Listening on port %d', server.address().port);

Start the app. Browse to http://localhost:3000 and submit a URL.

node app.js