How to Host a Static Website on Azure Blob Storage (Portal + CLI, and the HTTPS Catch)
A built React or plain HTML site does not need a web server — it needs a place to put files and a URL that serves them. Blob Storage does exactly that for pennies a month, as long as you know the one setting to flip and the one thing it cannot do.
New to cloud? CAMPUX is a free, build-first course. Start here →
To host a static website on Azure Blob Storage, turn on the Static website setting on a general-purpose v2 storage account; Azure creates a special $web container, you upload your built files there, and it serves them at a primary endpoint like https://<account>.z##.web.core.windows.net/ over HTTPS. Set an index document and a custom error page in the same setting. The catch — and the part most guides skip — is that a custom domain only gets HTTP from Storage alone; HTTPS on your own domain needs Azure Front Door or a CDN in front. Below is the whole path, portal and CLI, plus where this tool stops being the right one.
What Blob static website hosting actually is — the $web container
Static website hosting is a switch on a storage account, not a separate service you provision. Flip it on and Azure creates one container for you named $web. Anything you drop into $web is served to the public web through a dedicated endpoint over anonymous read access — no keys, no sign-in, just files going out over HTTPS. That is the entire mechanism: a container plus a web front door bolted onto it.
Two things about $web bite people, so learn them now. Its files are case-sensitive — index.html and Index.html are different files, and a mismatch is the most common source of a mystery 404. And the web endpoint is read-only; visitors can GET files but cannot write. If your build folder has an index.html, some CSS, JS, and images, this is all you need. For where this sits among the other storage services, see Blob, File, Queue, and Table storage explained, and for the account itself, the Azure storage account types.
Static website hosting needs a general-purpose v2 (or premium block blob) account. If you inherited an old general-purpose v1 account, the Static website blade will not appear. Create a fresh StorageV2 account and move on — it is not worth fighting an old one.
$web container: whatever you upload there is served straight to browsers, with an index document and a single custom error document. The default endpoint (<account>.z##.web.core.windows.net) already speaks HTTPS. The one wall: a custom domain only gets HTTPS if you put Azure Front Door (or CDN) in front — the storage account alone serves a custom domain over plain HTTP.Enable it in the portal + set index and error documents
In the portal, open your storage account, and in the left pane under Data management select Static website, then Enabled. Two fields appear:
- Index document name — the file served when someone hits a directory with no filename, almost always
index.html. - Error document path — an optional custom 404 page. Leave it blank and Azure returns a plain default 404.
Click Save. Azure creates $web if it does not already exist and shows you the primary endpoint URL right there on the blade — copy it. That is it for enabling; the rest is getting files in.
The same thing in the CLI is one command against the blob service properties:
az storage blob service-properties update \
--account-name mystaticsite \
--static-website \
--index-document index.html \
--404-document 404.html
Upload your site — portal, AzCopy, and az storage blob upload-batch
You have three sane ways to get a build into $web, and which you pick depends on how often you deploy.
For a one-off or a tiny site, the portal is fine: open the $web container under Containers and drag your files in. For anything you deploy more than once — a real build folder, a pipeline — script it. The Azure CLI pushes an entire directory in one shot:
az storage blob upload-batch \
--account-name mystaticsite \
-d '$web' \
-s ./dist
Quote '$web' in bash so the shell does not eat the $web as a variable — that single quoting mistake sends your files nowhere and leaves you staring at an empty site. AzCopy does the same job and tends to be faster on large trees, syncing a local folder up to the container. Both are what you wire into a deploy step; the portal is for the first look, not the tenth release.
| Method | Good for | Scriptable |
|---|---|---|
| Portal drag-and-drop | A handful of files, first look | No |
| AzCopy | Large build trees, fast sync | Yes |
az storage blob upload-batch | Deploy scripts and pipelines | Yes |
Finding and testing your primary endpoint
Your site lives at the primary endpoint, which takes the form https://<account>.z##.web.core.windows.net/ — note it is web.core.windows.net, not the blob.core.windows.net endpoint you use for regular blob access. The z## is a zone segment Azure assigns; do not hand-guess it. Read it off the Static website blade in the portal, or pull it from the CLI:
--name mystaticsite \
--query "primaryEndpoints.web" --output tsv
Open that URL and you should land on your index document. If you get a 404 at the root, the usual culprit is a case mismatch between the index name you set and the actual file in $web, or the file simply did not upload. Fix the case, re-upload, refresh.
The default endpoint is HTTPS out of the box. The padlock only gets complicated the moment you put your own domain in front of it.
The catch — custom domains only get HTTP unless you add Front Door/CDN
Here is the wall almost every quick tutorial walks you into and never mentions. That default *.web.core.windows.net endpoint is served over HTTPS already — you get TLS for free on it. But the second you map a custom domain like www.yoursite.com, Azure Storage will serve it over HTTP only. Storage natively supports mapping the domain; it does not yet natively support HTTPS on that custom domain.
To get the padlock on your own domain, you put Azure Front Door or a CDN in front of the static website endpoint and terminate TLS there. That is a second resource, a second bill, and a bit more DNS — not hard, but real work you should scope before you promise anyone a secure custom URL. It also buys you caching and headers, which the raw static website feature does not give you. If a custom domain with HTTPS is a day-one requirement, factor that layer in from the start rather than bolting it on after launch.
Enabling static website hosting is free — you pay only for the blob storage your files occupy and the operations to serve them, which for a small site is cents a month on a hot-tier account. That is the whole appeal. For how tiers change that math, see Blob storage access tiers.
When Blob static hosting is the wrong tool
This feature is narrow on purpose, and knowing its edges keeps you from forcing it. Reach for something else when:
- You need any authentication. Static website hosting does not support AuthN or AuthZ — everything in
$webis anonymous public read. If pages must sit behind a login, this is not your host. - You need server-side routing or rewrites. There is no rewrite engine. You get an index document and a single custom 404 page, full stop. A single-page app that relies on deep-link routing will 404 on refresh unless you handle it another way.
- You need redirects or custom headers. There is no way to set response headers or redirect rules in the feature itself; you would add a CDN or Front Door for that.
When those are your requirements, the right answers are usually Azure Static Web Apps — which adds built-in auth, routing config, and a GitHub CI/CD flow — or Azure App Service when you genuinely need a web server rendering content. But for a plain built site that just needs to be on the internet cheaply and reliably, Blob static website hosting is the boring, correct answer: flip the switch, push ./dist, share the endpoint.
Questions people also ask
Do I really need the static website setting to host a site in Blob Storage?
Yes, if you want a real website. You can make individual blobs public and link to them, but only the static website setting gives you a default index document, a custom 404 page, and a clean web endpoint that serves index.html at the root. Without it you are serving loose files, not a site.
What is the $web container in Azure Storage?
It is the special container Azure creates for you when you enable static website hosting. Files you put in $web are served through the site's primary endpoint over anonymous read access. Its contents are case-sensitive and read-only over the web endpoint, so index.html and Index.html are two different files.
Can I use a custom domain with an Azure Blob static website?
Yes. Azure Storage natively supports mapping a custom domain over HTTP. For HTTPS on that custom domain you have to put Azure Front Door or a CDN in front, because Storage does not yet natively support HTTPS with custom domains. Plan for that extra layer before you promise a padlock.
Does Azure Blob static website support HTTPS?
On the default endpoint, yes. Your primary endpoint of the form https://account.z##.web.core.windows.net is served over HTTPS out of the box. The limitation is custom domains: Azure Storage does not natively serve HTTPS for a custom domain, so you need Front Door or a CDN for that.
How do I upload files to the $web container?
Use the portal for a handful of files, or AzCopy or the Azure CLI for a whole build folder. The CLI command az storage blob upload-batch -d '$web' -s ./dist pushes an entire directory into $web in one shot, which is what you wire into a deploy script or pipeline.