GuidesBING
Bing image of the day API in JavaScript
Prefix https://proxy.cors.dev/ to Bing's HPImageArchive URL: free, no signup, no key, 600 requests per minute, up to 8 images per call. The JSON sends no Access-Control-Allow-Origin header, so fetch() from your page fails with a CORS error. The image files themselves load directly from bing.com in sizes from 320x240 to 3840x2160, so only the small JSON request, about 1 KB per image, goes through the proxy.
The HPImageArchive endpoint
Bing's homepage reads its daily photo from https://www.bing.com/HPImageArchive.aspx. Microsoft does not document it, but the shape is stable and it takes four parameters: format=js for JSON (or xml and rss), idx for how many days back to start, n for how many images, and mkt for the market.
idx=0&n=1 is today. n stops at 8 and idx stops at 7, so one call returns up to 8 days and two calls, idx=0&n=8 and idx=7&n=8, reach 15 days: today plus the 14 before it. Nothing older is available from this endpoint.
Show today's image
Each image has a urlbase such as /th?id=OHR.DolbadarnWales_EN-US6620614213. Append a size and .jpg to build the file URL; url is the same path with 1920x1080 filled in. title, copyright and copyrightlink give you the caption, the photo credit and a search link about the place.
// Runs in a module script or the DevTools console
async function bingImages({ market = 'en-US', daysAgo = 0, count = 1 } = {}) {
const url = `https://www.bing.com/HPImageArchive.aspx?format=js&idx=${daysAgo}&n=${count}&mkt=${market}`;
const response = await fetch('https://proxy.cors.dev/' + url, { credentials: 'omit' });
if (!response.ok) {
throw new Error(`Bing request failed: ${response.headers.get('X-Cors-Error') ?? response.status}`);
}
return (await response.json()).images;
}
const imageUrl = (image, size = '1920x1080') => `https://www.bing.com${image.urlbase}_${size}.jpg`;
const [today] = await bingImages();
document.body.style.background = `#111 center / cover no-repeat url("${imageUrl(today)}")`;
console.log(today.title, today.copyright, today.copyrightlink);Only the JSON goes through the proxy. The JPEG files send Access-Control-Allow-Origin: *, so they work in an <img> tag, in CSS backgrounds and in a canvas with crossOrigin = 'anonymous'. Routing them through cors.dev would fail anyway: the free tier relays text only and answers 502 unsupported_response for images.
A gallery of the last 15 days
Two calls in parallel cover the full window. The second call starts at day 7, which the first call already returned, so drop its first image.
// Uses bingImages() and imageUrl() from the example above. Markup: <div id="gallery"></div>
const [recent, older] = await Promise.all([bingImages({ count: 8 }), bingImages({ daysAgo: 7, count: 8 })]);
const days = [...recent, ...older.slice(1)];
document.querySelector('#gallery').replaceChildren(
...days.map((image) => {
const figure = document.createElement('figure');
const img = document.createElement('img');
img.src = imageUrl(image, '400x240');
img.alt = image.title;
img.loading = 'lazy';
const caption = document.createElement('figcaption');
caption.textContent = `${image.startdate}: ${image.copyright}`;
figure.append(img, caption);
return figure;
}),
);Image sizes
Append any of these suffixes to https://www.bing.com plus urlbase. File sizes are from one photo and vary from day to day.
| Suffix | Format | Sample size |
|---|---|---|
| _UHD.jpg | 3840x2160 landscape | 3.7 MB |
| _1920x1200.jpg | 16:10 landscape | 1.0 MB |
| _1920x1080.jpg | Full HD landscape | 339 KB |
| _1366x768.jpg | Laptop landscape | 171 KB |
| _1280x720.jpg | HD landscape | 193 KB |
| _1024x768.jpg | 4:3 landscape | 74 KB |
| _800x480.jpg | Thumbnail | 72 KB |
| _400x240.jpg | Small thumbnail | 20 KB |
| _320x240.jpg | Smallest thumbnail | 16 KB |
| _1080x1920.jpg | Phone portrait | 334 KB |
| _720x1280.jpg | Portrait | 216 KB |
| _480x800.jpg | Small portrait | 78 KB |
Markets, switch times and limits
mkt picks the regional edition. On the day checked, en-US, en-GB, de-DE and fr-FR showed the same photo, with the title translated for de-DE and fr-FR; ja-JP and zh-CN showed a different one, and en-IN a third. Each market switches at its own time: fullstartdate was 202610180700 for en-US and 202610181500 for ja-JP, midnight in US Pacific time and in Japan. enddate tells you the day the next image takes over, so cache until then.
- cors.dev free tier: GET and HEAD, 600 requests per minute per client IP, no daily or monthly quota, text responses up to 1 MiB. The image changes once a day, so one request per visitor per day is plenty.
- Copyright: the photos are licensed stock images, credited in
copyright. Showing them as a background is the common use; republishing them in a product needs a license from the rights holder. - No guarantees: the endpoint is undocumented, so keep the call in one function and fall back to a static image if it fails.
Good questions.
Is there an official Bing image of the day API?
Microsoft does not document one. HPImageArchive.aspx is the endpoint the Bing homepage itself uses; it needs no key and returns JSON, XML or RSS, but it can change without notice.
How do I get the 4K version?
Append _UHD.jpg to urlbase, for example https://www.bing.com/th?id=OHR.DolbadarnWales_EN-US6620614213_UHD.jpg. It is 3840x2160 and around 3.7 MB, so use a smaller size such as _1920x1080.jpg for page backgrounds.
How far back can I go?
Fifteen days: idx accepts 0 to 7 and n up to 8, so idx=7&n=8 ends 14 days before today. For an older archive, store each image yourself, for example with a scheduled job that runs once a day.
Why do I get a CORS error on the JSON but not on the image?
The JPEG responses send Access-Control-Allow-Origin: *, while HPImageArchive.aspx sends no CORS header at all. Images in img tags never need CORS anyway; only fetch() and canvas reads do.
Can I proxy the image file through cors.dev?
Not on the free tier, which relays text responses only and returns 502 unsupported_response for images. You do not need to: load the image straight from bing.com. Pro relays any content type up to 6 MiB if you have another reason to.
When does the Bing image change?
Each market has its own switch time, given in fullstartdate in UTC: 07:00 for en-US and 15:00 for ja-JP on the day checked, which is midnight local time in both. Read enddate and cache the result until then.