Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 63 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -283,31 +283,72 @@ For ease of use, some flags are set by default. However default flags are not us
```

## Using the CLI
HTML2image comes with a Command Line Interface which you can use to generate screenshots from files and URLs on the go.

The CLI is a work in progress and may undergo changes.
You can call it by typing `hti` or `html2image` into a terminal.


| argument | description | example |
| - | - | - |
| -h, --help | Shows the help message | `hti -h` |
| -U, --urls | Screenshots a list of URLs | `hti -U https://www.python.org` |
| -H, --html | Screenshots a list of HTML files | `hti -H file.html` |
| -C, --css | Attaches a CSS files to the HTML ones | `hti -H file.html -C style.css` |
| -O, --other | Screenshots a list of files of type "other" | `hti -O star.svg` |
| -S, --save-as | A list of the screenshot filename(s) | `hti -O star.svg -S star.png` |
| -s, --size | A list of the screenshot size(s) | `hti -O star.svg -s 50,50`|
| -o, --output_path| Change the output path of the screenshots (default is current working directory) | `hti star.svg -o screenshot_dir` |
| -q, --quiet| Disable all CLI's outputs | `hti --quiet` |
| -v, --verbose| More details, can help debugging | `hti --verbose` |
| --chrome_path| Specify a different chrome path ||
| --custom_flags| Specify custom browser flags |
| --temp_path| Specify a different temp path (where the files are loaded)||
HTML2image comes with a Command Line Interface which you can use to generate screenshots from files and URLs on the go. You can call it by typing `hti` or `html2image` into a terminal.


**Example Usage (quick start):**
Screenshot a URL with a specific output name and size:
```bash
hti --url https://example.com --save-as example_page.png --size 1280,720
```

Screenshot multiple HTML files, applying a common CSS file, and saving with custom names:
```bash
hti --html-file page1.html page2.html --css-file common_styles.css --save-as shot1.jpg shot2.jpg
```

Screenshot an HTML string with a custom browser flags and verbose output:
```bash
hti --html-string "<h1>Test</h1><p>Content</p>" --custom-flags '--no-sandbox' -v
```

**Html2Image Instance Configuration:**

These arguments configure the underlying `Html2Image` instance.

| Argument | Description | Example |
|----------|-------------|---------|
| `-h, --help` | Show the help message and exit. | `hti --help` |
| `-o, --output-path PATH` | Directory to save screenshots. (Default: current working directory)| `hti --url example.com -o my_images/` |
| `--browser BROWSER`| Browser to use. Choices: `chrome`, `chromium`, `google-chrome`, `google-chrome-stable`, `googlechrome`, `edge`, `chrome-cdp`, `chromium-cdp`. (Default: `chrome`)| `hti --url example.com --browser edge` |
| `--browser-executable EXECUTABLE_PATH` | Path to the browser executable. Auto-detected if not provided. | `hti --browser-executable /usr/bin/google-chrome-stable`|
| `--cdp-port PORT` | CDP port for CDP-enabled browsers (e.g., `chrome-cdp`). (Default: library-dependent)| `hti --browser chrome-cdp --cdp-port 9222 --url example.com` |
| `--temp-path TEMP_DIR_PATH` | Directory for temporary files. (Default: system temp directory in an `html2image` subfolder) | `hti --html-file page.html --temp-path /my/tmp`|
| `--keep-temp-files`| Do not delete temporary files after screenshot generation.| `hti --html-file page.html --keep-temp-files` |
| `--custom-flags [FLAG ...]` | Custom flags to pass to the browser (e.g., `'--no-sandbox' '--disable-gpu'`). If provided, these flags will be used. | `hti --url example.com --custom-flags '--no-sandbox' '--disable-gpu'` <br> `hti --url example.com --custom-flags '--no-sandbox --disable-gpu'` |

**Screenshot Sources:**

Specify what content to screenshot. At least one source type is required.

| Argument | Description | Example |
|----------|-------------|---------|
| `-U, --url [URL ...]` | URL(s) to screenshot. | `hti -U https://python.org https://example.com`|
| `--html-file [FILE ...]` | HTML file(s) to screenshot. | `hti --html-file mypage.html another.html` |
| `--html-string [STRING ...]`| HTML string(s) to screenshot. | `hti --html-string "<h1>Hello</h1>" "<h2>World</h2>"` |
| `--css-file [FILE ...]` | CSS file(s) to load. Used by HTML files or applied with HTML strings. | `hti --html-file page.html --css-file style1.css style2.css` |
| `--css-string [STRING ...]` | CSS string(s) to apply. Combined and used with HTML strings. | `hti --html-string "<h1>Hi</h1>" --css-string "body{color:red;}" "h1{font-size:40px;}"` |
| `-O, --other-file [FILE ...]` | Other file(s) to screenshot (e.g., SVG).| `hti -O star.svg`|

**Screenshot Output Options:**

Control how the screenshots are saved.

| Argument | Description | Example |
|----------|-------------|---------|
| `-S, --save-as [FILENAME ...]` | Filename(s) for output images. If not provided or fewer names than items, names are auto-generated (e.g., `screenshot.png`, `screenshot_0.png`). | `hti -U python.org example.com -S py.png ex.png` |
| `-s, --size [W,H ...]`| Size(s) for screenshots as `Width,Height`. If one W,H pair is given, it applies to all screenshots. If multiple W,H pairs are given, they apply to corresponding screenshots sequentially; if fewer pairs than items, the last pair is repeated. If omitted, the library's default (1920,1080) is used. Width and height must be positive integers. | `hti -U python.org --size 800,600` <br> `hti -U python.org example.com -s 800,600 1024,768` |

**General Options:**

| Argument | Description | Example |
|----------|-------------|---------|
| `-q, --quiet`| Suppress informational output from html2image library (sets `disable_logging=True`). | `hti -U python.org -q` |
| `-v, --verbose` | Enable verbose output, including browser commands if supported by the browser handler. | `hti -U python.org -v` |

<br>

### ... now within a Docker container !
### Using a Docker Container

You can also test the package and the CLI without having to install everything on your local machine, via a Docker container.

Expand Down
264 changes: 215 additions & 49 deletions html2image/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,81 +2,247 @@
"""

import argparse

import os
from html2image import Html2Image


def main():

def size_type(string):
try:
x, y = map(int, string.split(','))
return x, y
except Exception:
def size_type(string):
try:
width, height = map(int, string.split(','))
if width <= 0 or height <= 0:
raise argparse.ArgumentTypeError(
f"size should be int,int, instead got {string}"
'Width and height must be positive integers.'
)
return width, height
except ValueError: # incorrect number of values
raise argparse.ArgumentTypeError(
f"Size should be W,H (e.g., 1920,1080), instead got '{string}'"
)
except Exception as e: # unexpected errors
raise argparse.ArgumentTypeError(f"Invalid size format '{string}': {e}")

parser = argparse.ArgumentParser()

parser.add_argument('-U', '--url', nargs='*', required=False, default=[])
parser.add_argument('-H', '--html', nargs='*', required=False, default=[])
parser.add_argument('-C', '--css', nargs='*', required=False, default=[])
parser.add_argument('-O', '--other', nargs='*', required=False, default=[])
def main():
parser = argparse.ArgumentParser(
description='Generate images from HTML/CSS or URLs using the html2image library.',
formatter_class=argparse.ArgumentDefaultsHelpFormatter
)

# Html2Image instantiation arguments
group_hti_init = parser.add_argument_group('Html2Image Instance Configuration')
group_hti_init.add_argument(
'--output-path', '-o',
default=os.getcwd(),
help='Directory to save screenshots.'
)

parser.add_argument(
'-S', '--save-as', nargs='*', required=False, default="screenshot.png"
# TODO : this list is duplicated from browser_map in html2image.py
browser_choices = [
'chrome', 'chromium', 'google-chrome', 'google-chrome-stable',
'googlechrome', 'edge', 'chrome-cdp', 'chromium-cdp'
]
group_hti_init.add_argument(
'--browser',
default='chrome',
choices=browser_choices,
help='Browser to use for screenshots.'
)
parser.add_argument(
'-s', '--size', nargs='*', required=False, default=[], type=size_type
group_hti_init.add_argument(
'--browser-executable',
default=None,
help='Path to the browser executable. Auto-detected if not provided.'
)
group_hti_init.add_argument(
'--cdp-port',
type=int,
default=None,
help='CDP port for CDP-enabled browsers (e.g., chrome-cdp). Default is library-dependent.'
)
group_hti_init.add_argument(
'--temp-path',
default=None,
help="Directory for temporary files. Defaults to system temp directory within an 'html2image' subfolder."
)
group_hti_init.add_argument(
'--keep-temp-files',
action='store_true',
help='Do not delete temporary files after screenshot generation.'
)
group_hti_init.add_argument(
'--custom-flags',
nargs='*',
default=[], # If not provided, defaults are used
help="Custom flags to pass to the browser (e.g., '--no-sandbox' '--disable-gpu'). If provided, these flags will be used."
)

parser.add_argument('-o', '--output_path', required=False)
# Screenshot sources arguments
group_sources = parser.add_argument_group('Screenshot Sources (at least one type is required)')
group_sources.add_argument(
'--url', '-U',
nargs='*', default=[],
metavar='URL',
help='URL(s) to screenshot.'
)
group_sources.add_argument(
'--html-file',
nargs='*', default=[],
metavar='FILE',
help='HTML file(s) to screenshot.'
)
group_sources.add_argument(
'--html-string',
nargs='*', default=[],
metavar='STRING',
help='HTML string(s) to screenshot.'
)
group_sources.add_argument(
'--css-file',
nargs='*', default=[],
metavar='FILE',
help='CSS file(s) to load. Used by HTML files or applied with HTML strings.'
)
group_sources.add_argument(
'--css-string',
nargs='*', default=[],
metavar='STRING',
help='CSS string(s) to apply. Combined and used with HTML strings.'
)
group_sources.add_argument(
'--other-file', '-O',
nargs='*', default=[],
metavar='FILE',
help='Other file(s) to screenshot (e.g., SVG).'
)

parser.add_argument('-q', '--quiet', required=False, action="store_true")
parser.add_argument('-v', '--verbose', required=False, action="store_true")
# Screenshot output control arguments
group_output_ctrl = parser.add_argument_group('Screenshot Output Options')
group_output_ctrl.add_argument(
'--save-as', '-S',
nargs='*', default=None, # html2image handles default naming if only one source
metavar='FILENAME',
help='Filename(s) for the output images. If not provided or fewer names than items, names are auto-generated.'
)
group_output_ctrl.add_argument(
'--size', '-s',
nargs='*', default=[],
type=size_type,
metavar='W,H',
help="Size(s) for screenshots as W,H. If one W,H pair is given, it applies to all. If multiple, they apply to corresponding screenshots; if fewer pairs than items, the last is repeated. If omitted, (1920,1080) is used."
)

# parser.add_argument('--browser', required=False)
parser.add_argument('--chrome_path', required=False)
# parser.add_argument('--firefox_path', required=False)
parser.add_argument('--temp_path', required=False)
parser.add_argument('--custom_flags', required=False)
# General arguments
group_general = parser.add_argument_group('General Options')
group_general.add_argument(
'--quiet', '-q',
action='store_true',
help='Suppress output from browsers (sets disable_logging=True).'
)
group_general.add_argument(
'--verbose', '-v',
action='store_true',
help='Enable verbose output, including browser commands if supported by the browser handler.'
)

args = parser.parse_args()

# Prepare Html2Image()
hti_kwargs = {
'output_path': args.output_path,
'browser': args.browser,
'browser_executable': args.browser_executable,
'custom_flags': [cf.replace("'", '') for cf in args.custom_flags],
'disable_logging': args.quiet,
'temp_path': args.temp_path,
'keep_temp_files': args.keep_temp_files,
}

# Only pass cdp_port if a CDP browser is likely selected and port is given
if args.cdp_port and 'cdp' in args.browser.lower():
hti_kwargs['browser_cdp_port'] = args.cdp_port
elif args.cdp_port:
print(
f"Warning: --cdp-port ({args.cdp_port}) was specified, but the selected browser ('{args.browser}') might not be a CDP browser."
)

try:
hti = Html2Image(disable_logging=args.quiet)
# Filter out None values so defaults are used for those specific kwargs
# keep_temp_files and disable_logging are bools, always pass them.
# custom_flags should be passed even if None, so Html2Image can use its defaults or an empty list.
active_hti_kwargs = {
k: v for k, v in hti_kwargs.items()
if v is not None or k in ['keep_temp_files', 'disable_logging', 'custom_flags']
}
hti = Html2Image(**active_hti_kwargs)

except Exception as e:
print('Could not instanciate html2image.')
print(e)
print(f'Error: Could not instantiate Html2Image: {e}')
exit(1)

if args.verbose:
print(f'args = {args}')
hti.browser.print_command = True

if args.output_path:
hti.output_path = args.output_path
# The `print_command` attribute is specific to ChromiumHeadless.
# CDP browsers print logs internally.
if hasattr(hti.browser, 'print_command'):
hti.browser.print_command = True
print('Verbose mode: Browser commands will be printed for compatible handlers.')
else:
print('Verbose mode enabled. Note: Detailed browser command printing depends on the selected browser handler.')

has_sources = any([
args.url, args.html_file, args.html_string, args.other_file
])

# Print help message if no sources were passed
if not has_sources:
print('Error: No screenshot sources (URL, HTML file/string, other file) provided.')
parser.print_usage()
exit(1)

if args.chrome_path:
hti.chrome_path = args.chrome_path
# Perform screenshot
screenshot_kwargs = {
'url': args.url,
'html_file': args.html_file,
'html_str': args.html_string,
'css_file': args.css_file,
'css_str': args.css_string,
'other_file': args.other_file,
'size': args.size, # Pass the list of sizes directly from the --size CLI arg
}

if args.custom_flags:
hti.browser.flags = args.custom_flags
if args.save_as is not None:
screenshot_kwargs['save_as'] = args.save_as

if args.temp_path:
hti.temp_path = args.temp_path
try:
if args.verbose:
print('--- Html2Image Instance Configuration ---')
for k, v in active_hti_kwargs.items():
print(f' {k}: {v}')
print('--- Screenshot Call Arguments ---')
for k, v in screenshot_kwargs.items():
if v or k == 'size': # print if list not empty, or always for size
print(f' {k}: {v}')

paths = hti.screenshot(**screenshot_kwargs)

if not args.quiet:
print(f'Successfully created {len(paths)} image(s):')
for path in paths:
print(f' {path}')

except FileNotFoundError as e:
print(f'Error: A required file was not found: {e}')
exit(1)

paths = hti.screenshot(
html_file=args.html, css_file=args.css, other_file=args.other,
url=args.url, save_as=args.save_as, size=args.size
)
except ValueError as e: # Can be raised by browser screenshot method for bad size etc.
print(f'Error: Invalid value encountered: {e}')
exit(1)

if not args.quiet:
print(f'Created {len(paths)} file(s):')
for path in paths:
print(f'\t{path}')
except Exception as e:
print(f'An unexpected error occurred during screenshotting: {e}')
if args.verbose:
import traceback
traceback.print_exc()
exit(1)


if __name__ == "__main__":
if __name__ == '__main__':
main()
Loading
Loading