---
title: "Rate Limits and Caching for Agents and Crawlers | Hamlet's Friends"
description: "No per-client rate limit and no 429 on hamletsfriends.com. What Cache-Control says for pages and text files, and how often internet status changes."
url: "https://hamletsfriends.com/rate-limits/"
locale: "en"
lastmod: "2026-10-15"
alternates:
  en: "https://hamletsfriends.com/rate-limits/"
  x-default: "https://hamletsfriends.com/rate-limits/"
site_index: "https://hamletsfriends.com/llms.txt"
---
# Rate limits

What this host enforces, which is nothing, and how often its data changes.

## No enforced limit and no 429

Nothing on hamletsfriends.com counts requests per client today, and no endpoint answers 429 Too Many Requests. The site is small and its content changes only when we publish, so there is rarely a reason to fetch the same file twice in a few minutes.

## How long a copy stays fresh

Static files come from the Azure Static Web Apps edge network. Each response says in Cache-Control how long your copy stays fresh. Send If-None-Match with the ETag you got, and an unchanged file comes back as 304 with no body. Every deploy changes every ETag, so right after a deploy even an unchanged file comes back as 200.

**Table: Cache-Control by resource**

| Resource | Cache-Control |
| --- | --- |
| Pages | public, must-revalidate, max-age=30 |
| Markdown twins, /pricing.md, /facts.md | public, max-age=300, must-revalidate |
| /llms.txt, /llms-full.txt, /robots.txt, /sitemap.xml, /openapi.json | public, max-age=3600, must-revalidate |
| /api/internet-status | no-store |

curl

```bash
ETAG=$(curl -sI https://hamletsfriends.com/pricing.md | awk 'tolower($1)=="etag:"{print $2}' | tr -d '\r')
curl -s -o /dev/null -w "%{http_code}\n" -H "If-None-Match: $ETAG" https://hamletsfriends.com/pricing.md
```

JavaScript

```javascript
const first = await fetch('https://hamletsfriends.com/pricing.md');
const etag = first.headers.get('etag');
const again = await fetch('https://hamletsfriends.com/pricing.md', {
  headers: { 'If-None-Match': etag },
});
console.log(again.status); // 304 while the file is unchanged
```

Response

```http
HTTP/2 304
```

## Internet status changes every five minutes at most

/api/internet-status serves a stored snapshot. A request refreshes it only when the snapshot is more than five minutes old, and a scheduled job is set to refresh it every five minutes as well. Polling faster returns the same data, so compare updatedAt and poll every five minutes at most. Access rules are on the [authentication page](https://hamletsfriends.com/authentication/).

curl

```bash
curl -s https://hamletsfriends.com/api/internet-status \
  -H "x-status-password: $HF_STATUS_PASSWORD" | jq .updatedAt
```

JavaScript

```javascript
const FIVE_MINUTES = 5 * 60 * 1000;
setInterval(async () => {
  const response = await fetch('https://hamletsfriends.com/api/internet-status', {
    headers: { 'x-status-password': process.env.HF_STATUS_PASSWORD },
  });
  const { updatedAt, internet } = await response.json();
  console.log(updatedAt, internet.level);
}, FIVE_MINUTES);
```
