Build a screenshot downloader app with plain JavaScript in 10 minutes
Tags: javascript, css, tutorial, beginners
Published: 2021-10-21 19:47:16

Recently I stumbled across a cool tool for taking instant screenshots from any website. 

 [ScreenshotAPI ](https://www.screenshotapi.net/) is an API tool which allows you capture and render a screenshot of any website by making a single API query from your script.

I found that quite interesting, so I decided to build something based on such feature.

In this tutorial, we will be building a screenshot downloader app from scratch, making use of HTML, CSS, JavaScript, and the screenshot API.


![ezgif.com-gif-maker (4).gif](https://cdn.hashnode.com/res/hashnode/image/upload/v1634648653449/iAwf4rPlO.gif)

You can instantly grab the code for this project from  [CodePen](https://codepen.io/ubahthebuilder/pen/JjyKbRQ?editors=1010) 

### Create an account on ScreenshotAPI and get a token
To proceed, we will be needing an API token for executing the query. To obtain your token, you will be required to  [sign up first](https://www.screenshotapi.net/) .

![Sign Up for Screenshot API](https://cdn.hashnode.com/res/hashnode/image/upload/v1634644662442/xTWjiwObu.png)
 
Go ahead and sign up. You will also be instructed to validate your email, so make sure to do that (check spam folder as well)

After the email validation process, you will be moved to the dashboard from your profile. There you will find your API key. Copy and preserve the API token.

### HTML Markup for the Screenshot Taking App
Create an index.html file, create the boilerplate code (`!+tab` in emmet) and use the markup below inside the body tags:

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Screenshot Downloader</title>
    <link rel="stylesheet" href="styles.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta2/css/all.min.css" integrity="sha512-YWzhKL2whUzgiheMoBFwW8CKV4qpHQAEuvilg9FAn5VJUDwKZZxkJNuGM4XkWuk94WCrrwslk8yWNGmY1EduTA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
</head>
<body>

  <div class="container">
    <div class="form">
      <div class="title flex">
        <h1 id="title">Screenshot Downloader</h1>
        <i class="fa fa-camera-retro fa-2x" aria-hidden="true"></i>
      </div>
      <input id="url" type="text" placeholder="Enter url to screenshot">
      <button id="btn" type="submit">Take Screenshot</button>
    </div>

    <div class="image">
      Wait for your screenshot to appear below.

      <span class="reference"></span>
    </div>
  </div>

    <script src="script.js" type="text/javascript"></script>
</body>
</html>

```

> 
NOTE: We are using Font Awesome for the camera icon

The entire app goes into a container. In the form we have a title, text input and button. We use `.flex` class to display both children `h1` and `i` side-by-side.

After the form, we have the section for the image. At the moment, the `div` is empty. However, when a url is submitted and a screenshot is returned, this div will be populated by that screenshot image.

The `<span>` tag is just for reference. We will use it to specify where to insert the image from JavaScript.

Finally, we link to our JavaScript file. And here is the look of our page (without styling)

![App without CSS](https://cdn.hashnode.com/res/hashnode/image/upload/v1634645441551/DeOPduXEP.png)

### Styling The App
The styling is quite straight-forward. I have included some comments to explain what each of them do.

```css
/* Align the body to the center. Align all text within the body to center as well. Set background-color to light blue */

body{
  font-family: "rubik", sans-serif;
  display: flex;
  align-items: center;
  text-align: center;
  justify-content: center;
  background-color: #ADD8E6;
}

/* Change the color of the icon to grey */

i {
  color: grey;
  margin: 0 1rem;
}

/* Ensure that containing box is at the center. Set a max-width so content doesn't burst out of container */

.container {
  margin: 50px auto;
  max-width: 1100px;
}

/* Set height of image container to 50 percent of browser window's height and width to 40 percent of window's width. Sets backround to white. Make the border rounder, and increase font size */

.image {
  margin-top: 10vh;
  height: 50vh;
  width: 40vw;
  font-size: 2rem;
  background-color: white;
  border-radius: 6px;
}

/* Create a class for the eventual screenshot image. This image will not be present at the start. The class will be passed to the new image from JavaScript */

.screenshot {
  height: 100%;
  width: 100%;
}

/* Display title and icon side by side */

.flex {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Set padding, margin and font-size. Removes border line and make border rounder */

#url {
  padding: .7rem .7rem;
  margin: .3rem .3rem;
  font-size: 1rem;
  border: none;
  border-radius: 6px;
}

/* Same styles with input. Set cursor to pointer and background to blue */

#btn {
  padding: .7rem .7rem;
  margin: .3rem .3rem;
  background-color: blue;
  border: none;
  font-size: 1rem;
  border-radius: 6px;
  color: white;
  cursor: pointer;
}
```

### Implement Screenshot functionality with JavaScript
First in our script will be an `async` function called `loadImage()`. As you might have guessed, this function will be responsible for generating the screenshot.

```js
async function loadImage() {
 // get url value from from field and token from dashboard. Construct URL 

  let formUrl = document.getElementById('url').value
  let token = "GA0KVYA-EQ94WNV-GKMC33C-3JZKQ3F"
  let url = `https://shot.screenshotapi.net/screenshot?token=${token}&url=${formUrl}`

 // Make a get request to screenshotnet API and get response object
  const response = await fetch(url)
  const object = await response.json()


  //create a new image element
  let newImg = document.createElement('img')

  // set class on that element
  newImg.className= 'screenshot'

 // set src property with the images' url from response object
  newImg.setAttribute('src', object.screenshot)

 // get the nodes where you want to insert the new image
  let container = document.querySelector('.image')
  let reference = document.querySelector('.reference')

/* check if an image already exists. if so, simply replace that image. if not, then insert the new image before the reference element (<span>) */
  if (document.images.length >= 1 ) {
      let existingImg = document.querySelector('.screenshot')
      container.replaceChild(newImg, existingImg)
  } else {
      container.insertBefore(newImg, reference)
  }

}

```

> 
NOTE: Comments are for code explanation. They are not part of the executable code

Finally, we add an event listener to the button. When it gets clicked, we want to try loading the screenshot.

```js
// Get reference to button 
let button = document.getElementById('btn')

// add event listener, run an async function when button gets clicked

button.addEventListener("click", async (event) => {
    
    // prevent from submission
    event.preventDefault()

    try {
      loadImage()
    } catch(e) {
      console.log("Error!");
      console.log(e);
    }
})
``` 

You can get the full code from  [Codepen](https://codepen.io/ubahthebuilder/pen/JjyKbRQ?editors=1010) 

### Summary
So in this tutorial, we built a screenshot taking app with some HTML, CSS and JavaScript. 

In the script, we make a query to screenshots API passing in our desired website to the url parameter as well as the API token to the token parameter. The API responds with an object from which we can obtain the screenshot URL and render using JavaScript.

I hope you enjoyed this tutorial. You can check out the code and tweak it to your taste.

Thanks for following along.