Deployment guide

Crawl4AI

Videos

Overview: Crawl4AI on Ubuntu 24.04 on Azure: overview (watch on YouTube)

Launch and log in: Crawl4AI on Ubuntu 24.04 on Azure: launch and log in (watch on YouTube)

Deep Dive: Crawl4AI on Ubuntu 24.04 on Azure: deep dive (watch on YouTube)

Overview

Crawl4AI is a fast, open-source web crawler and scraper. It converts web pages into clean, LLM-ready Markdown and structured data through a simple REST API. It drives a headless Chromium browser, so it renders JavaScript-heavy pages the way a real browser sees them. It returns Markdown tuned for large language model context, plus screenshots, PDF capture, on-page JavaScript execution and streaming or asynchronous job endpoints.

This SecureAnyCloud image runs the official Crawl4AI server (unclecode/crawl4ai:0.9.2) as a Docker container bound to loopback 127.0.0.1:11235, behind nginx on port 80. nginx is ready for your TLS certificate.

The image is secure by default and never exposes an open crawl endpoint, because an unauthenticated web crawler is a server-side request forgery and denial-of-service risk. Crawl4AI binds to host loopback only and natively enforces a bearer API token on every API endpoint. The crawl4ai-firstboot.service oneshot generates a unique token on each VM's first boot.

What you get:

  • Crawl4AI 0.9.2 as the official server Docker container, with headless Chromium bundled
  • docker.service running the container bound to 127.0.0.1:11235
  • An nginx reverse proxy on port 80, ready for TLS
  • crawl4ai-firstboot.service, a oneshot that generates a unique API token on each VM's first boot, sets it on the container and writes it to a root-only 0600 file. It also resolves the instance URL and writes a root-only info note.
  • No shared tokens: no two VMs share a token, and none is baked into the image
  • An unauthenticated /healthz endpoint that stays open for monitoring
  • An Ubuntu 24.04 LTS base, patched at build time
  • 24/7 SecureAnyCloud support, 24h response SLA

Prerequisites

You need an active Azure subscription, an SSH key pair, and a VNet with a subnet.

Crawl4AI drives a real headless Chromium browser, which is memory-sensitive. Use Standard_B2s (2 vCPU, 4 GB RAM) for evaluation and light crawling, or Standard_D2s_v5 or larger for concurrent or heavy crawling.

The crawler needs outbound internet access to fetch the pages you ask it to crawl.

1

Deploy from the Azure Portal

Search the Azure Marketplace for Crawl4AI on Ubuntu 24.04 and choose your VM size.

Attach a network security group (NSG) that allows TCP 22 (SSH) from your management network, and TCP 80 and 443 (the crawl API) from the networks and applications that will call it. In production, front port 80 with TLS (see Enabling HTTPS below).

2

Deploy from the Azure CLI

# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:crawl4ai-ubuntu-24-04:default:latest
az vm create \
  --resource-group my-rg \
  --name crawl4ai-01 \
  --image sac1647283583153:crawl4ai-ubuntu-24-04:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard
# Open the crawl API port to the callers that need it
az vm open-port --resource-group my-rg --name crawl4ai-01 --port 80

First boot takes a few minutes. The VM finishes its per-VM setup in the background, generating its own credentials and starting the services. If you connect as soon as the VM shows as running, wait for that setup to complete before continuing by running sudo cloud-init status --wait.

It prints status: done when the VM is ready. The credentials and services described below exist only after that.

3

Verify the services and retrieve your API token

SSH in as azureuser. First boot creates the container, generates your per-VM API token and brings the stack up. Confirm that the services are healthy:

systemctl is-active docker nginx
sudo docker ps --format '{{.Names}}\t{{.Status}}' curl -s -o /dev/null -w 'healthz: HTTP %{http_code}\n' http://127.0.0.1/healthz

Expected output:

active active crawl4ai Up 3 minutes (healthy) healthz: HTTP 200

Crawl4AI listens only on host loopback 127.0.0.1:11235, and nginx fronts it on port 80.

Read your unique API token from the root-only info note:

sudo cat /root/crawl4ai-info.txt

The file (mode 0600, owned by root) contains your CRAWL4AI_URL and CRAWL4AI_TOKEN. The token is unique to this VM and was generated on first boot. Keep it secret.

With a Standard SKU public IP (the Azure default), CRAWL4AI_URL can show the VM's private address, for example http://10.0.0.4/. From outside the VNet, call the API at your VM's public IP or DNS name instead.

4

Verify the API token gate

Crawl4AI enforces your API token on every crawl request. A request with no token or a wrong token is rejected with HTTP 401, and only your per-VM token is accepted. Verify this from the VM:

TOKEN=$(sudo grep '^CRAWL4AI_TOKEN=' /root/crawl4ai-info.txt | cut -d= -f2-)
echo "no token -> HTTP $(curl -s -o /dev/null -w '%{http_code}' -X POST http://127.0.0.1/crawl -H 'Content-Type: application/json' -d '{"urls":["https://example.com"]}')"
echo "wrong token-> HTTP $(curl -s -o /dev/null -w '%{http_code}' -X POST http://127.0.0.1/crawl -H 'Authorization: Bearer wrong' -H 'Content-Type: application/json' -d '{"urls":["https://example.com"]}')"
echo "your token -> HTTP $(curl -s -o /dev/null -w '%{http_code}' -X POST http://127.0.0.1/md -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{"url":"https://example.com"}')"

Expected output:

no token -> HTTP 401 wrong token-> HTTP 401 your token -> HTTP 200
5

Your first crawl

The /md endpoint turns a page into clean Markdown in a single call. Pass your token as a bearer header:

TOKEN=$(sudo grep '^CRAWL4AI_TOKEN=' /root/crawl4ai-info.txt | cut -d= -f2-)
curl -s -X POST http://127.0.0.1/md \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com"}' | jq -r .markdown

Expected output is the Markdown of the page, starting with its text. example.com changes its wording from time to time, so yours may differ:

This domain is for use in documentation examples without needing permission. This is not a service; avoid relying on it for testing and monitoring purposes.

From a remote machine, replace 127.0.0.1 with your VM's address and use the same token. In production, put TLS in front (see Enabling HTTPS below) and call https://your-domain/md.

6

Full crawl with structured output

The /crawl endpoint returns the full result set, including the raw HTML, links, media and several Markdown variants. Use it when you need more than plain Markdown:

TOKEN=$(sudo grep '^CRAWL4AI_TOKEN=' /root/crawl4ai-info.txt | cut -d= -f2-)
curl -s -X POST http://127.0.0.1/crawl \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"urls":["https://example.com"],"crawler_config":{"type":"CrawlerRunConfig","params":{"cache_mode":"bypass"}}}' \
  | jq -r '.results[0] | "url: " + .url, "status: " + (.status_code|tostring), "links: " + (.links.internal|length|tostring), "markdown chars: " + (.markdown.raw_markdown|length|tostring)'

Expected output:

url: https://example.com status: 200 links: 0 markdown chars: 953

The character count follows the page's current content, so expect a different number for other pages or after example.com changes.

Crawl4AI also exposes /html (sanitised HTML), /screenshot (a PNG of the rendered page), /pdf (a PDF), /execute_js (run JavaScript on the page), and streaming and job endpoints. See the Crawl4AI documentation for the full API and its extraction options.

7

Updates, persistence and patching

The container image is pinned at build time, and first boot pulls and recreates it cleanly, so every VM starts from a known-good image. The container runs with a restart policy, so it survives reboots.

Check the container's restart policy and whether any packages are held back:

sudo docker inspect -f 'image: {{index .Config.Image}} restart: {{.HostConfig.RestartPolicy.Name}}' crawl4ai systemctl is-enabled crawl4ai-firstboot.service docker nginx apt-mark showhold

Expected output:

image: unclecode/crawl4ai:0.9.2 restart: unless-stopped enabled enabled enabled

The empty last line from apt-mark showhold confirms that no security updates are held back. The Ubuntu base is patched at build time and ships with unattended security upgrades enabled.

Enabling HTTPS

nginx fronts Crawl4AI on port 80 and is ready for your certificate. For a public domain, point an A record at the VM, then install a certificate with Certbot:

sudo apt-get update
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.example.com

Certbot obtains and installs the certificate, reloads nginx for HTTPS on port 443, and sets up automatic renewal. After that, call the API at https://your-domain.example.com/md.

Use your NSG to restrict ports 80 and 443 to the networks that need the crawler. To rotate the API token, recreate the container with a new CRAWL4AI_API_TOKEN. The command is in /root/crawl4ai-info.txt.

Support

Every SecureAnyCloud deployment includes 24/7 support with a 24-hour response SLA. Contact sales@secureanycloud.com for help with deployment, configuration or scaling.

Crawl4AI is open-source software licensed under the Apache License 2.0. This is a repackaged open-source product, with additional charges for SecureAnyCloud support services. Crawl4AI is a trademark of its respective owner.

Deploy on Azure

Launch Crawl4AI on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure