Have you ever needed to automatically take screenshots of websites – maybe to track visual changes, add them to reports, or generate previews? Doing this manually can be time-consuming, especially if you need to capture multiple pages regularly.
In this tutorial, you will learn how to create a simple website screenshot generator using Python and Flask. The app will let users enter any website URL and instantly get a screenshot of that page – all powered by the Screenshot API.
You will use Flaska lightweight web framework for building a simple web interface and handling applications. Next, you’ll integrate an external API to programmatically capture website screenshots.
By the end of this tutorial, you will learn how to:
Create a basic Flask web app
Accept user input via an HTML form
Make HTTP requests to an external API
Display images dynamically on a web page
This project is a great way to learn how APIs can extend the capabilities of your web applications, and how Python can easily handle tasks like image generation and display.
What we will cover:
Conditions
Before we start building the app, make sure you have some basics covered:
1. Python is installed
You will need to have Python 3.9 or higher installed on your machine. You can check your version by running:
python --version
If you don’t have it, you can download it python.org/downloads.
2. Basic knowledge of Python and Flask
You don’t need to be a flask expert. Some familiarity with ways to create routes and templates, and how to handle form data in Flask.
If you’re new to Flask, don’t worry—we’ll go step-by-step.
3. Screenshot API key
We will use Screenshot base API Capturing website screenshots. It provides a simple REST endpoint that takes a URL and fetches a screenshot image.
You can get a free API key by signing up on their website. Once you have your key, keep it handy, as we will use it when we integrate the API in later steps.
4. A code editor and terminal
You can use any editor you prefer, such as VS Code, Pycharm, or even a simple text editor. Make sure your terminal or command prompt can run Python commands and install packages using pip.
Project establishment
Let’s start by setting up a new Flask project from scratch.
Step 1: Create a new folder
Create a new folder for your project. You can name it screenshot-generator:
mkdir screenshot-generator
cd screenshot-generator
Step 2: Create the virtual environment
A virtual environment helps isolate your project’s dependencies from other Python projects.
Run the following commands:
python -m venv venv
Then activate it:
On macOS/Linux:
source venv/bin/activateOn Windows:
venv\Scripts\activate
Once activated, you should see (venv) At the beginning of your terminal prompt.
Step 3: Install Dependencies
We will need two packages for this project:
Install them using PIP:
pip install flask requests
Step 4: Set up the project structure
Inside your project folder, create the following files and folders:
screenshot-generator/
├── app.py
├── templates/
│ └── index.html
└── static/
Here’s what each part does:
app.py: The main Python file that runs your Flask apptemplates/: Stores HTML templatesstatic/: Stores images, CSS, and JavaScript files
Step 5: Add a Basic Flask App
open app.py And add the following starter code:
from flask import Flask, render_template, request
import requests
import os
app = Flask(__name__)
API_KEY = os.getenv("SCREENSHOTBASE_API_KEY")
SCREENSHOTBASE_BASE_ENDPOINT = "
@app.route('/', methods=('GET', 'POST'))
def home():
if request.method == 'POST':
url = request.form.get('url')
return render_template('index.html', url=url)
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True)
This determines the minimum flask application with a route (/) we will add the screenshot base API call in the next section.
Step 6: Create a simple HTML template
Now that we’ve written the Flask backend to handle the screenshot request, let’s create the frontend for our app.
Inside your project folder, create a new directory named templatesand inside that, add a file called index.html. Flask will automatically search for templates in this folder.
Here’s how the template should look:
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Website Screenshot Generatortitle>
<link
href="
rel="stylesheet"
integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB"
crossorigin="anonymous"
/>
<style>
body {
padding-top: 2rem;
}
.screenshot-container {
max-height: 80vh;
overflow-y: auto;
border: 1px solid #ddd;
border-radius: 8px;
padding: 1rem;
background: #f8f9fa;
}
style>
head>
<body>
<div class="container text-center">
<h1 class="mb-4">Website Screenshot Generatorh1>
<form method="POST" class="d-flex justify-content-center mb-4">
<input
type="text"
name="url"
placeholder="Enter website URL"
class="form-control w-50 me-2"
required
>
<button type="submit" class="btn btn-primary">Capture Screenshotbutton>
form>
{% if screenshot %}
<h4>Screenshot Preview:h4>
<div class="screenshot-container mx-auto">
<img src="{{ screenshot }}" alt="Website Screenshot" class="img-fluid rounded shadow">
div>
{% elif request.method == 'POST' %}
<div class="alert alert-danger mt-3">
Sorry, something went wrong while capturing the screenshot. Please try again.
div>
{% endif %}
div>
body>
html>
This HTML template uses Bootstrap to keep the design clean and responsive without any custom styling. The form at the top allows users to enter any website URL and submit it to the Flask app using POST Method Once the app retrieves the screenshot URL from the API, it dynamically renders the image on the page.
img-fluid The bootstrap class ensures that the screenshot scales properly across all screen sizes while maintaining its aspect ratio. Also, .screenshot-container Provides a scrollable area, which helps display full-page screenshots without shrinking too much or breaking the layout.
Now your project is ready to capture real screenshots using ScreenshotBase API.
In the next section, we’ll write the logic to call the Screenshot base API and dynamically display the screenshot in the browser.
Integrating the Screenshot Base API
Now that our Flask app is set up, let’s connect it to the Screenshot Base API so we can generate real screenshots from any URL.
Step 1: Understanding the API endpoint
The Screenshot Base API provides a simple endpoint that takes a website URL and returns a screenshot image.
A typical API call looks like this:
GET
You pass the target website URL as a query parameter (url) and add your API key to the request header apikey.
Here is an example of curl from their documentation:
curl -G ?url=https%3A%2F%2Fbbc.com \
-H "apikey: YOUR-API-KEY"
Screenshot captured in this application and returns the screenshot image as the response.
Step 2: Add an API call to Flask
Let’s update us home On the way app.py To send a request to the Screenshot base API when a user submits a URL.
Here is the latest version app.py:
from flask import Flask, render_template, request
import requests
import os
app = Flask(__name__)
API_KEY = os.getenv("SCREENSHOTBASE_API_KEY")
SCREENSHOTBASE_BASE_ENDPOINT = "
@app.route('/', methods=('GET', 'POST'))
def home():
screenshot_url = None
if request.method == 'POST':
target_url = request.form.get('url')
params = {"url": target_url}
headers = {"apikey": API_KEY}
try:
response = requests.get(SCREENSHOTBASE_BASE_ENDPOINT, params=params, headers=headers, timeout=30)
response.raise_for_status()
image_path = os.path.join('static', 'screenshot.png')
with open(image_path, 'wb') as f:
f.write(response.content)
screenshot_url = image_path
except requests.exceptions.RequestException as e:
print(f"Error capturing screenshot: {e}")
return render_template('index.html', screenshot=screenshot_url)
if __name__ == '__main__':
app.run(debug=True)
What this code does:
Captures user input (URL).
Sends a gate request
/v1/takeEnd pointpasses your API key in the request header (
apikey)Saves the returned image
staticFolderDisplays a screenshot on the page.
Step 3: Test your app
Run the app again:
python app.py
Enter a URL such as:
After submission, you should see a screenshot of this website displayed at the bottom of the form.
Your Flask app is now fully functional! It takes a URL, sends it to the screenshot base API, and displays the resulting screenshot.

In the next section, we’ll extend the app by adding customization options like full-page screenshots, viewport settings, and delay. Later, we’ll explore the Screenshot Base SDK for popular languages like Python, NodeJS, and PHP.
Adding customization options
Right now, our app takes a screenshot of a given website URL using default settings. However, most screenshot APIs (including the one we’re using) allow you to customize the output by passing additional parameters to the request.
The Screenshot Base API offers several powerful customization options to help tailor each screenshot to your needs:
Image formatSelect from :
pngfor , for , for , .jpgfor , for , for , .giforwebpdepending on your image quality or compression needs.Full page capture: capture the entire scrollable web page (
full_page=1) or visible-only viewports (full_page=0)Viewport dimensions: Set with browser window size
viewport_widthAndviewport_heightTo simulate screenshots from desktop, tablet, or mobile screens.
These options make the screenshot base ideal for building automation tools, thumbnail generators, testing dashboards, and visual documentation systems. Let’s add these options to make our screenshot generator more flexible.
Updating Flask Code
Open your app.py file and update that handles submissions to include these optional parameters:
from flask import Flask, render_template, request
import requests
import os
app = Flask(__name__)
API_KEY = os.getenv("SCREENSHOTBASE_API_KEY", "scr_live_9Qkn1gs01rivZqrFk7lusXPiqAUg85J86aU6bHvG")
SCREENSHOTBASE_BASE_ENDPOINT = "
@app.route('/', methods=('GET', 'POST'))
def home():
screenshot_url = None
if request.method == 'POST':
target_url = request.form.get('url')
format_ = request.form.get('format', 'png')
full_page = request.form.get('full_page') == 'on'
params = {
"url": target_url,
"format": format_,
"full_page": int(full_page)
}
headers = {"apikey": API_KEY}
try:
response = requests.get(SCREENSHOTBASE_BASE_ENDPOINT, params=params, headers=headers, timeout=30)
response.raise_for_status()
image_extension = format_ if format_ != 'jpeg' else 'jpg'
image_path = os.path.join('static', f'screenshot.{image_extension}')
with open(image_path, 'wb') as f:
f.write(response.content)
screenshot_url = image_path
except requests.exceptions.RequestException as e:
print(f"Error capturing screenshot: {e}")
return render_template('index.html', screenshot=screenshot_url)
if __name__ == '__main__':
app.run(debug=True)
Updating the HTML template
Next, let’s edit our form index.html To add customization options:
<form method="POST" class="d-flex flex-column justify-content-center mb-4">
<div class="input-group mb-4">
<input
type="text"
name="url"
placeholder="Enter website URL"
class="form-control w-50 me-2"
required
/>
<button type="submit" class="btn btn-primary">Capture Screenshotbutton>
div>
<div class="row g-3">
<div class="col-md-6">
<div class="form-check">
<input
type="checkbox"
name="full_page"
id="full_page"
class="form-check-input"
/>
<label class="form-check-label" for="full_page">
Capture Full Page Screenshot
label>
div>
div>
<div class="col-md-6">
<label for="format" class="form-label">Screenshot Formatlabel>
<select class="form-select" name="format" id="format" required>
<option value="png">PNGoption>
<option value="jpg">JPGoption>
<option value="gif">GIFoption>
<option value="webp">WEBPoption>
select>
div>
<div class="col-md-6">
<label for="viewport_width" class="form-label">Viewport Widthlabel>
<input
type="number"
name="viewport_width"
id="viewport_width"
class="form-control"
value="1280"
min="320"
/>
div>
<div class="col-md-6">
<label for="viewport_height" class="form-label">Viewport Heightlabel>
<input
type="number"
name="viewport_height"
id="viewport_height"
class="form-control"
value="720"
min="320"
/>
div>
div>
form>
The latest form gives users control over how the screenshot is generated. The format dropdown lets them choose between PNG, JPG, GIF, or WEBP. The Full Page checkbox toggles whether the API captures the entire scrollable web page or just the visible viewport. The viewport width and height fields define the dimensions of the browser window, which is useful if you want to simulate different device sizes or responsive layouts.
When the form is submitted, Flask reads these values and sends them as query parameters to the API request.
For example, a full page capture request of your site, a 1920×1080 PNG screenshot would look like this:
?url=https%3A%2F%2Fgithub.com%2Fashutoshkrris&format=png&full_page=1&viewport_width=1920&viewport_height=1080
This flexibility makes it easy to fine-tune screenshots for different use cases—whether you’re generating thumbnails, testing responsiveness, or automating visual reports.

Note: If you prefer to work with SDKs instead of direct API calls, the Screenshot base also offers official SDKs for popular languages such as Python, JavaScript, Ruby, PHP, and Go.
These SDKs provide a simple and convenient way to interact with the API, handling authentication and formatting behind the scenes.
You can find them Screenshot base SDK documentation.
wrap up
In this tutorial, you learned how to develop a simple Flask application that captures website screenshots using a third-party API. We figured out how to send requests, handle image response, and add customization options like image format, full-page capture, and viewport size—while keeping the project lightweight and easy to extend.
This small project demonstrates how web automation tasks, such as generating previews or visual reports, can be simplified using modern APIs. You can build on this foundation to integrate screenshots into batch screenshot tools, visual monitoring systems, or even large web applications.
The key takeaway is understanding how to interact with external APIs, process responses, and designing a clean interface for users. These are skills that are common to backend and full-stack developers alike.