How to Convert an HTM File to JPG for Free
Convert an HTM file to JPG with free online, local-browser, command-line, and ScreenshotNeo methods, plus fixes for missing assets and layout problems.
Short answer: an .htm file must be rendered by a browser engine before it can become a JPG. The simplest free workflow is to open or upload the file to an HTML-to-image converter, choose JPG, set the viewport and quality, render it, and download the image. For private files, use a converter that processes locally in your browser or run a headless browser on your own machine.
.htm and .html are functionally equivalent extensions for this task. Conversion is a render-and-capture operation, not a byte-for-byte image re-encoding: CSS, fonts, JavaScript, viewport size, and external assets determine the pixels in the result.
1. Choose the right free method
| Method | Best for | Privacy | Main limitation |
|---|---|---|---|
| Online converter | Fast, one-off conversions | File is sent to a hosted service | Local assets or scripts may not load |
| Local browser converter | Confidential files | File stays on your device when the tool explicitly supports no-upload processing | Browser support and output options vary |
| Headless Chrome or Playwright | Repeatable automation and CI | You control the machine | Requires setup and asset troubleshooting |
| Screenshot API | Production workflows and remote URLs | Page is rendered by the provider | Requires an API key |
2. Convert HTM to JPG with an online tool
- Save the complete HTM package. Keep relative images, CSS, JavaScript, and fonts beside the file.
- Open a converter such as CoolUtils HTML to JPG or JPG.now HTM to JPG.
- Upload or drop the
.htmfile. - Choose JPG and set quality, viewport width, JavaScript timing, or full-page capture when those controls are available.
- Render the page and download the JPG.
Hosted tools are convenient, but review the service’s current privacy terms before uploading confidential source files. If the page references images/photo.png, css/site.css, or a web font, a converter receiving only the HTML file may not be able to resolve those paths.
3. Convert privately in your browser
FileFlip describes an in-browser WebAssembly workflow, and PixelTools likewise says HTML rendering and conversion happen in the browser without an upload. Drop the HTM file, leave JPG selected, adjust the available dimensions or quality controls, and save the result.
Use this route when the file contains private data. Still check the tool’s current privacy statement, because implementation and retention policies can change. Local processing does not repair missing sibling assets: keep the original folder structure and open the file from that folder.
4. Use a browser manually
- Open the HTM file in Chrome by dragging it into a tab or using File > Open File.
- Inspect the page at the viewport width you need. Responsive CSS can produce a different layout at mobile and desktop widths.
- For a document-style result, use File > Print (Chrome documents opening a file and printing in its Help documentation).
- For an image, use a browser screenshot utility that can capture the rendered page, then export or convert the capture to JPG.
JPG is lossy. Use a high quality setting for text, and choose PNG instead when you need transparency or very sharp small text.
5. Automate conversion with Playwright
This local Node.js example renders an HTM file in Chromium and writes a JPG. It keeps the source on your machine.
npm install playwright
npx playwright install chromium
const { chromium } = require('playwright');
const path = require('path');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage({
viewport: { width: 1440, height: 900 },
deviceScaleFactor: 1
});
const filePath = path.resolve(process.argv[2] || 'page.htm');
await page.goto('file://' + filePath, { waitUntil: 'load' });
await page.waitForTimeout(500); // allow fonts or scripts to settle
await page.screenshot({
path: process.argv[3] || 'page.jpg',
type: 'jpeg',
quality: 90,
fullPage: true
});
await browser.close();
})();
node convert.js ./report.htm ./report.jpg
If your HTM uses JavaScript to load content, wait for a meaningful selector instead of relying only on a fixed delay:
await page.goto('file://' + filePath, { waitUntil: 'networkidle' });
await page.locator('#report-ready').waitFor({ state: 'visible', timeout: 15000 });
6. Python automation with Selenium
python -m pip install selenium pillow
from pathlib import Path
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from PIL import Image
source = Path('report.htm').resolve()
options = Options()
options.add_argument('--headless=new')
options.add_argument('--window-size=1440,900')
driver = webdriver.Chrome(options=options)
try:
driver.get(source.as_uri())
driver.implicitly_wait(2)
driver.save_screenshot('report.png')
finally:
driver.quit()
# Selenium writes PNG; convert it to JPG.
with Image.open('report.png').convert('RGB') as image:
image.save('report.jpg', quality=90, optimize=True)
For a full-page capture, set the browser window to the document’s required width and either use a browser-specific full-page technique or capture sections and stitch them. A very long document can produce an impractically tall JPG.
7. Render a hosted HTM URL with ScreenshotNeo
When the HTM page is available at an HTTPS URL, ScreenshotNeo renders it with a browser and returns PNG, JPEG, WebP, or PDF. It supports full-page capture with lazy images loaded, element capture by CSS selector, custom viewport and retina scale, dark mode, waits, custom CSS and JavaScript, headers, cookies, user agents, request blocking, caching, and more. See the ScreenshotNeo API documentation for the complete parameter list.
cURL
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://example.com/report.htm \
-d format=jpg \
-d full_page=true \
-d quality=90 \
-o report.jpg
Python
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={
"access_key": "YOUR_API_KEY",
"url": "https://example.com/report.htm",
"format": "jpg",
"full_page": "true",
"quality": 90,
},
timeout=90,
)
r.raise_for_status()
open("report.jpg", "wb").write(r.content)
Node.js
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://example.com/report.htm',
format: 'jpg',
full_page: 'true',
quality: '90'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
require('fs').writeFileSync('report.jpg', Buffer.from(await res.arrayBuffer()));
Making a local HTM reachable
An API cannot normally fetch a private file:// path on your computer. For local development, serve the directory temporarily (for example, with python -m http.server) and expose it through an access-controlled HTTPS tunnel, or deploy the page to a staging URL. Do not publish confidential files just to create a screenshot.
8. Control the rendered result
- Viewport: choose the width that matches the intended desktop, tablet, or mobile layout.
- Full page versus viewport: full-page output includes content below the fold and may be extremely tall.
- Wait conditions: wait for a selector, a delay, network idle, web fonts, and lazy-loaded images.
- Assets: package relative images, stylesheets, scripts, and fonts with the HTM file, or make them available at stable HTTPS URLs.
- JPG quality: increase quality for text and diagrams; reduce it for smaller files.
- Transparency: JPG has no alpha channel. Flatten transparent backgrounds or use PNG.
- Responsive CSS: verify breakpoints at the chosen viewport before converting.
- Dynamic content: freeze clocks, animations, carousels, and personalized data when repeatability matters.
9. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Images are blank | Relative paths, blocked cross-origin requests, or unavailable files | Preserve the folder structure, use valid URLs, and check the browser console/network log. |
| Styles are missing | CSS file was not included or the path is wrong | Open the HTM from its original directory and include its CSS files. |
| Text uses the wrong font | Web font has not loaded or is inaccessible | Wait for fonts, bundle them locally, or use a reliable HTTPS font URL. |
| JavaScript content is absent | Capture happened before the script finished | Wait for a selector or network idle; increase the timeout. |
| Mobile layout appears on desktop | Viewport is too narrow | Set an explicit desktop viewport width before capture. |
| Output is excessively tall | Full-page capture includes every section | Capture the viewport, capture an element, or split the document into sections. |
| JPG looks blurry | Low quality, low device scale, or repeated recompression | Use quality around 90, increase device scale, and convert only once. |
| API returns an error | Invalid key, unreachable URL, timeout, or unsupported parameter | Check the HTTP status and response body, verify the URL from an external network, and consult the docs. |
10. Performance, reliability, and cost
Local conversion has no service charge, but it uses your CPU, memory, browser installation, and network. Hosted conversion is easier to repeat, while rendering time increases with large pages, slow assets, JavaScript, full-page stitching, and high-resolution output. Cache stable pages when possible, avoid unnecessary third-party resources, and set a timeout that matches the page’s real load time.
ScreenshotNeo bills only clean shots. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and each response reports the result in X-Page-Verdict and X-Billed headers. Plans include 1,000 free shots per month with no card; paid plans start at $5 for 3,000 shots. Yearly billing provides two months free.
11. Or skip the browser setup
For a hosted HTM page, one ScreenshotNeo request returns the JPG:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com/report.htm -d format=jpg -o report.jpg
Cookie banners, newsletter popups, and chat widgets are removed before the shot. Bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents take screenshots, and 1,000 screenshots a month are free with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.
12. FAQ
Can I convert HTM to JPG without uploading the file?
Yes. Use a local browser converter or run Playwright/Selenium on your computer. These methods keep the source local unless your page itself loads remote resources.
Is HTM different from HTML?
No practical difference for browser rendering. Both extensions contain HTML markup.
Why does the JPG differ from what I see in my editor?
The editor preview may use a different viewport, fonts, permissions, or timing. The capture reflects the browser engine and resources available at render time.
Should I use PNG instead?
Use PNG for transparency or crisp text and diagrams. Use JPG for smaller photographic or document images when some loss is acceptable.
Can an API convert a file on my laptop?
Not directly. Give the API a reachable URL, or perform the conversion locally with a headless browser.


