Html2image
A package acting as a wrapper around the headless mode of existing web browsers to generate images from URLs and from HTML+CSS strings or files.
Install / Use
/learn @vgalin/Html2imageREADME
|PyPI Package|GitHub Repository| |-|-|
A lightweight Python package acting as wrapper around the headless mode of existing web browsers, allowing image generation from HTML/CSS strings, files and URLs.
</div> This package has been tested on Windows, Ubuntu (desktop and server) and MacOS. If you encounter any problems or difficulties while using it, feel free to open an issue on the GitHub page of this project. Feedback is also welcome!
⚠️ Disclaimer: Use this package with trusted content only. Processing untrusted or unsanitized input can lead to malicious code execution. Always ensure content safety.
Principle
Most web browsers have a Headless Mode, which is a way to run them without displaying any graphical interface. Headless mode is mainly used for automated testing but also comes in handy if you want to take screenshots of web pages that are exact replicas of what you would see on your screen if you were using the browser yourself.
However, for the sake of taking screenshots, headless mode is not very convenient to use. HTML2Image aims to hide the inconveniences of the browsers' headless modes while adding useful features, such as allowing the creation of images from simple strings.
For more information about headless modes :
- (Chrome) https://developers.google.com/web/updates/2017/04/headless-chrome
- (Firefox) https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Headless_mode
Installation
HTML2Image is published on PyPI and can be installed through pip:
pip install --upgrade html2image
Or with uv:
uv pip install html2image
In addition to this package, at least one of the following browsers must be installed on your machine :
- Google Chrome (Windows, MacOS)
- Chromium Browser (Linux)
- Microsoft Edge
Usage
First, import the package and instantiate it
from html2image import Html2Image
hti = Html2Image()
Multiple arguments can be passed to the constructor:
browser: Browser that will be used, can be set to'chrome'(default) or'edge'.browser_executable: The path or the command that can be used to find the executable of a specific browser.output_path: Path to the folder to which taken screenshots will be outputted. Default is the current working directory of your python program.size: 2-Tuple representing the size of the screenshots that will be taken. Default value is(1920, 1080).temp_path: Path that will be used to put together different resources when screenshotting strings of files. Default value is%TEMP%/html2imageon Windows, and/tmp/html2imageon Linux and MacOS.keep_temp_files: Pass True to this argument to not automatically remove temporary files created intemp_path. Default is False.
Example:
hti = Html2Image(size=(500, 200))
You can also change these values later:
hti.size = (500, 200)
Then take a screenshot
The screenshot method is the basis of this package. Most of the time, you won't need to use anything else. It can take screenshots of various things:
- URLs via the
urlparameter; - HTML and CSS files via the
html_fileandcss_fileparameters; - HTML and CSS strings via the
html_strandcss_strparameters; - and "other" types of files via the
other_fileparameter (try it with .svg files!).
And you can also (optional):
- Change the size of the screenshots using the
sizeparameter; - Save the screenshots as a specific name using the
save_asparameter.
N.B.: The screenshot method returns a list containing the path(s) of the screenshot(s) it took.
A few examples
- URL to image
hti.screenshot(url='https://www.python.org', save_as='python_org.png')
- HTML & CSS strings to image
html = """<h1> An interesting title </h1> This page will be red"""
css = "body {background: red;}"
hti.screenshot(html_str=html, css_str=css, save_as='red_page.png')
- HTML & CSS files to image
hti.screenshot(
html_file='blue_page.html', css_file='blue_background.css',
save_as='blue_page.png'
)
- Other files to image
hti.screenshot(other_file='star.svg')
- Change the screenshots' size
hti.screenshot(other_file='star.svg', size=(500, 500))
<details> <summary> Click to show all the images generated with all the code above </summary> <img src="readme_assets/sample_url_to_img.png" alt="sample_url_to_img.png"/> <img src="readme_assets/sample_strings_to_img.png" alt="sample_strings_to_img"/> <img src="readme_assets/sample_files_to_img.png" alt="sample_files_to_img"/> <img src="readme_assets/sample_other.png" alt="sample_other_to_img"/> <img src="readme_assets/sample_other_50_50.png" alt="sample_other_50_50"/> </details>
- Change the directory to which the screenshots are saved
hti = Html2Image(output_path='my_screenshot_folder')
OR
hti.output_path = 'my_screenshot_folder'
N.B. : the output path will be changed for all future screenshots.
Use lists in place of any parameters while using the screenshot method
- Screenshot multiple objects using only one filename, or one filename per file:
# create three files from one filename
hti.screenshot(html_str=['A', 'B', 'C'], save_as='ABC.png')
# outputs ABC_0.png, ABC_1.png, ABC_2.png
# create three files from from different filenames
hti.screenshot(html_str=['A', 'B', 'C'], save_as=['A.png', 'B.png', 'C.png'])
# outputs A.png, B.png, C.png
- Take multiple screenshots with the same size
# take four screenshots with a resolution of 100*50
hti.screenshot(
html_str=['A', 'B', 'C', 'D'],
size=(100, 50)
)
- Take multiple screenshots with different sizes
# take four screenshots with different resolutions from three given sizes
hti.screenshot(
html_str=['A', 'B', 'C', 'D'],
size=[(100, 50), (100, 100), (50, 50)]
)
# respectively 100*50, 100*100, 50*50, 50*50
# if not enough sizes are given, the last size in the list will be repeated
- Apply CSS string(s) to multiple HTML string(s)
# screenshot two html strings and apply css strings on both
hti.screenshot(
html_str=['A', 'B'],
css_str='body {background: red;}'
)
# screenshot two html strings and apply multiple css strings on both
hti.screenshot(
html_str=['A', 'B'],
css_str=['body {background: red;}', 'body {font-size: 50px;}']
)
# screenshot one html string and apply multiple css strings on it
hti.screenshot(
html_str='A',
css_str=['body {background: red;}', 'body {font-size: 50px;}']
)
- Retrieve the path of the generated file(s)
Thescreenshotmethod returns a list containing the path(s) of the screenshot(s):
paths = hti.screenshot(
html_str=['A', 'B', 'C'],
save_as="letters.png",
)
print(paths)
# >>> ['D:\\myFiles\\letters_0.png', 'D:\\myFiles\\letters_1.png', 'D:\\myFiles\\letters_2.png']
Change browser flags
In some cases, you may need to change the flags that are used to run the headless mode of a browser.
Flags can be used to:
- Change the default background color of the pages;
- Hide the scrollbar;
- Add delay before taking a screenshot;
- Allow you to use Html2Image when you're root, as you will have to specify the
--no-sandboxflag;
You can find the full list of Chrome / Chromium flags here.
There are two ways to specify custom flags:
# At the object instanciation
hti = Html2image(custom_flags=['--my_flag', '--my_other_flag=value'])
# Afterwards
hti.browser.flags = ['--my_flag', '--my_other_flag=value']
- Flags example use-case: adding a delay before taking a screenshot
With Chrome / Chromium, screenshots are fired directly after there is no more "pending network fetches", but you may sometimes want to add a delay before taking a screenshot, to wait for animations to end for example.
There is a flag for this purpose, --virtual-time-budget=VALUE_IN_MILLISECONDS. You can use it like so:
hti = Html2Image(
custom_flags=['--virtual-time-budget=10000', '--hide-scrollbars']
)
hti.screenshot(url='http://example.org')
- Default flags
For ease of use, some flags are set by default. However default flags are not used if you decide to specify custom_flags or change the value of browser.flags:
# Taking a look at the default flags
>>> hti = Html2Image()
>>> hti.browser.flags
['--default-background-color=000000', '--hide-scrollbars']
# Changing the value of browser.flags gets rid of the default flags.
>>> hti.browser.flags = ['--1', '--2']
>>> hti.browser.flags
['--1', '--2']
# Using the custom_flags pa
Related Skills
node-connect
345.4kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
claude-opus-4-5-migration
104.6kMigrate prompts and code from Claude Sonnet 4.0, Sonnet 4.5, or Opus 4.1 to Opus 4.5
frontend-design
104.6kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
model-usage
345.4kUse CodexBar CLI local cost usage to summarize per-model usage for Codex or Claude, including the current (most recent) model or a full model breakdown. Trigger when asked for model-level usage/cost data from codexbar, or when you need a scriptable per-model summary from codexbar cost JSON.
