How to Render a Weather Widget as an Image
Render a weather widget as a PNG. Useful for digital signage, daily-briefing emails and weather-app share cards.
HTML Content
<div class="weather-widget">
<div class="current-weather">
<div class="weather-icon">
<svg viewBox="0 0 24 24" width="64" height="64">
<path fill="currentColor" d="M12,7A5,5 0 0,1 17,12A5,5 0 0,1 12,17A5,5 0 0,1 7,12A5,5 0 0,1 12,7M12,9A3,3 0 0,0 9,12A3,3 0 0,0 12,15A3,3 0 0,0 15,12A3,3 0 0,0 12,9M12,2L14.39,5.42C13.65,5.15 12.84,5 12,5C11.16,5 10.35,5.15 9.61,5.42L12,2M3.34,7L7.5,6.65C6.9,7.16 6.36,7.78 5.94,8.5C5.5,9.24 5.25,10 5.11,10.79L3.34,7M3.36,17L5.12,13.23C5.26,14 5.53,14.78 5.95,15.5C6.37,16.24 6.91,16.86 7.5,17.37L3.36,17M20.65,7L18.88,10.79C18.74,10 18.47,9.23 18.05,8.5C17.63,7.78 17.1,7.15 16.5,6.64L20.65,7M20.64,17L16.5,17.36C17.09,16.85 17.62,16.22 18.04,15.5C18.46,14.77 18.73,14 18.87,13.21L20.64,17M12,22L9.59,18.56C10.33,18.83 11.14,19 12,19C12.82,19 13.63,18.83 14.37,18.56L12,22Z" />
</svg>
</div>
<div class="temp-info">
<div class="temperature">28°C</div>
<div class="description">Sunny</div>
</div>
</div>
<div class="weather-details">
<div class="detail">
<div class="label">Humidity</div>
<div class="value">65%</div>
</div>
<div class="detail">
<div class="label">Wind</div>
<div class="value">12 km/h</div>
</div>
<div class="detail">
<div class="label">UV Index</div>
<div class="value">6</div>
</div>
</div>
<div class="location">
<svg viewBox="0 0 24 24" width="16" height="16">
<path fill="currentColor" d="M12,11.5A2.5,2.5 0 0,1 9.5,9A2.5,2.5 0 0,1 12,6.5A2.5,2.5 0 0,1 14.5,9A2.5,2.5 0 0,1 12,11.5M12,2A7,7 0 0,0 5,9C5,14.25 12,22 12,22C12,22 19,14.25 19,9A7,7 0 0,0 12,2Z" />
</svg>
<span>San Francisco, CA</span>
</div>
<div class="forecast">
<div class="forecast-item">
<div class="day">MON</div>
<div class="icon">☀️</div>
<div class="temp">29°</div>
</div>
<div class="forecast-item">
<div class="day">TUE</div>
<div class="icon">⛅</div>
<div class="temp">27°</div>
</div>
<div class="forecast-item">
<div class="day">WED</div>
<div class="icon">🌤️</div>
<div class="temp">28°</div>
</div>
<div class="forecast-item">
<div class="day">THU</div>
<div class="icon">🌥️</div>
<div class="temp">26°</div>
</div>
</div>
</div>
CSS Styles
body {
margin: 0;
padding: 24px;
background: white;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}
.weather-widget {
width: 300px;
background: linear-gradient(135deg, #4c6ef5, #228be6);
color: white;
border-radius: 16px;
padding: 24px;
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.1);
}
.current-weather {
display: flex;
align-items: center;
margin-bottom: 24px;
}
.weather-icon {
margin-right: 16px;
}
.temperature {
font-size: 48px;
font-weight: 700;
line-height: 1;
margin-bottom: 4px;
}
.description {
font-size: 16px;
opacity: 0.9;
}
.weather-details {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
padding: 16px 0;
border-top: 1px solid rgba(255, 255, 255, 0.1);
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
margin-bottom: 16px;
}
.detail {
text-align: center;
}
.label {
font-size: 12px;
opacity: 0.8;
margin-bottom: 4px;
}
.value {
font-size: 16px;
font-weight: 600;
}
.location {
display: flex;
align-items: center;
font-size: 14px;
opacity: 0.9;
margin-bottom: 24px;
}
.location svg {
margin-right: 6px;
}
.forecast {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 8px;
}
.forecast-item {
text-align: center;
font-size: 14px;
}
.day {
opacity: 0.8;
margin-bottom: 4px;
}
.icon {
font-size: 20px;
margin: 4px 0;
}
.temp {
font-weight: 600;
}
API Request
POST https://app.html2img.com/api/html
{
"html": "<div class=\"weather-widget\"><div class=\"current-weather\"><div class=\"weather-icon\"><svg viewBox=\"0 0 24 24\" width=\"64\" height=\"64\"><path fill=\"currentColor\" d=\"M12,7A5,5 0 0,1 17,12A5,5 0 0,1 12,17A5,5 0 0,1 7,12A5,5 0 0,1 12,7M12,9A3,3 0 0,0 9,12A3,3 0 0,0 12,15A3,3 0 0,0 15,12A3,3 0 0,0 12,9M12,2L14.39,5.42C13.65,5.15 12.84,5 12,5C11.16,5 10.35,5.15 9.61,5.42L12,2M3.34,7L7.5,6.65C6.9,7.16 6.36,7.78 5.94,8.5C5.5,9.24 5.25,10 5.11,10.79L3.34,7M3.36,17L5.12,13.23C5.26,14 5.53,14.78 5.95,15.5C6.37,16.24 6.91,16.86 7.5,17.37L3.36,17M20.65,7L18.88,10.79C18.74,10 18.47,9.23 18.05,8.5C17.63,7.78 17.1,7.15 16.5,6.64L20.65,7M20.64,17L16.5,17.36C17.09,16.85 17.62,16.22 18.04,15.5C18.46,14.77 18.73,14 18.87,13.21L20.64,17M12,22L9.59,18.56C10.33,18.83 11.14,19 12,19C12.82,19 13.63,18.83 14.37,18.56L12,22Z\" /></svg></div><div class=\"temp-info\"><div class=\"temperature\">28°C</div><div class=\"description\">Sunny</div></div></div><div class=\"weather-details\"><div class=\"detail\"><div class=\"label\">Humidity</div><div class=\"value\">65%</div></div><div class=\"detail\"><div class=\"label\">Wind</div><div class=\"value\">12 km/h</div></div><div class=\"detail\"><div class=\"label\">UV Index</div><div class=\"value\">6</div></div></div><div class=\"location\"><svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\"><path fill=\"currentColor\" d=\"M12,11.5A2.5,2.5 0 0,1 9.5,9A2.5,2.5 0 0,1 12,6.5A2.5,2.5 0 0,1 14.5,9A2.5,2.5 0 0,1 12,11.5M12,2A7,7 0 0,0 5,9C5,14.25 12,22 12,22C12,22 19,14.25 19,9A7,7 0 0,0 12,2Z\" /></svg><span>San Francisco, CA</span></div><div class=\"forecast\"><div class=\"forecast-item\"><div class=\"day\">MON</div><div class=\"icon\">☀️</div><div class=\"temp\">29°</div></div><div class=\"forecast-item\"><div class=\"day\">TUE</div><div class=\"icon\">⛅</div><div class=\"temp\">27°</div></div><div class=\"forecast-item\"><div class=\"day\">WED</div><div class=\"icon\">🌤️</div><div class=\"temp\">28°</div></div><div class=\"forecast-item\"><div class=\"day\">THU</div><div class=\"icon\">🌥️</div><div class=\"temp\">26°</div></div></div></div>",
"width": 348,
"height": 355,
"css": "body{margin:0;padding:0;background:white;font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,sans-serif}.weather-widget{width:300px;background:linear-gradient(135deg,#4c6ef5,#228be6);color:white;border-radius:16px;padding:24px;box-shadow:0 4px 24px rgba(0,0,0,0.1)}.current-weather{display:flex;align-items:center;margin-bottom:24px}.weather-icon{margin-right:16px}.temperature{font-size:48px;font-weight:700;line-height:1;margin-bottom:4px}.description{font-size:16px;opacity:0.9}.weather-details{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;padding:16px 0;border-top:1px solid rgba(255,255,255,0.1);border-bottom:1px solid rgba(255,255,255,0.1);margin-bottom:16px}.detail{text-align:center}.label{font-size:12px;opacity:0.8;margin-bottom:4px}.value{font-size:16px;font-weight:600}.location{display:flex;align-items:center;font-size:14px;opacity:0.9;margin-bottom:24px}.location svg{margin-right:6px}.forecast{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}.forecast-item{text-align:center;font-size:14px}.day{opacity:0.8;margin-bottom:4px}.icon{font-size:20px;margin:4px 0}.temp{font-weight:600}"
}
Update the weather data, location, and forecast information to match your needs.
How it Works
- Modern gradient background with weather information
- SVG icons for weather conditions
- Grid layout for weather details and forecast
- Responsive design that works well on any device
The widget uses emoji for forecast icons which may render differently across platforms. Use SVG icons for consistent results.
Code in other languages
Node.js
const response = await fetch('https://app.html2img.com/api/html', {
method: 'POST',
headers: { 'X-API-Key': process.env.HTML2IMG_API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ html: weatherHtml, css: weatherCss, width: 600, height: 400 }),
});
const { url } = await response.json();
Python
import os, requests
response = requests.post(
'https://app.html2img.com/api/html',
headers={'X-API-Key': os.environ['HTML2IMG_API_KEY']},
json={'html': weather_html, 'css': weather_css, 'width': 600, 'height': 400},
)
url = response.json()['url']
PHP
$ch = curl_init('https://app.html2img.com/api/html');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['X-API-Key: ' . getenv('HTML2IMG_API_KEY'), 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode(['html' => $weatherHtml, 'css' => $weatherCss, 'width' => 600, 'height' => 400]),
]);
$url = json_decode(curl_exec($ch), true)['url'];
Common pitfalls
- Emoji icons render inconsistently. Replace emoji with self-hosted SVGs so the widget looks the same in every render.
- Temperature unit drift. Always include the unit in the rendered string (“72F” or “22C”) so the image is unambiguous.
- Long city names overflow. Use
text-overflow: ellipsison the location label or pre-truncate in your data layer.