Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.bunny.net/llms.txt

Use this file to discover all available pages before exploring further.

bunny.net provides raw request logs for all Pull Zones with Logging Enabled. Logs appear in near real-time and they’re retained for 3 days. For longer retention, use Permanent Log Storage to automatically archive logs to Edge Storage. We expose two HTTP APIs for accessing logs:
  • Logging API v2 - recommended. Structured JSON, rich filtering, pagination, and per-field search.
  • Logging API v1 - legacy. Streams a raw pipe-delimited file for a given day; preserved for existing integrations.

Privacy & GDPR

IP addresses are anonymized by default. To enable full IP logging, sign the Data Processing Agreement (DPA) in your account settings, then disable anonymization in your Pull Zone logging settings. When anonymization is enabled, anonymized IPs are returned by the API in one of two forms depending on your Pull Zone setting:
  • Remove last octet - IPv4 is masked to a /24 (e.g. 163.172.53.0); IPv6 is masked to a /64 (e.g. 2001:7d0:700d:db04::).
  • Drop all - IPv4 becomes 0.0.0.0 and IPv6 becomes ::.
Anonymization applies on read at the API boundary. Filtering by remoteIp adapts to the same mask width, so the filter can never reveal information beyond what the response shows.

Logging API v2

GET https://logging.bunnycdn.com/v2/pullzones/{pullZoneId}/logs
Authenticate with your account API key or a bearer JWT:
AccessKey: your-api-key
# or
Authorization: Bearer <jwt>
Logs are retained for the past 3 days. Both from and the range to - from must fall within that window.

Example

curl -H "AccessKey: your-api-key" \
     "https://logging.bunnycdn.com/v2/pullzones/1337/logs?from=2026-05-08T00:00:00Z&to=2026-05-09T00:00:00Z&status=4xx,5xx&limit=50"

Query parameters

ParameterTypeDescription
fromISO 8601 UTCInclusive start of the time range. Defaults to to - 24h. Must fall within the 3-day retention window.
toISO 8601 UTCExclusive end of the time range. Defaults to now.
statuscomma listHTTP status filter. Each entry is either an exact code (200, 404) or a class (2xx, 5xx). Multiple entries are OR-ed.
cacheStatuscomma listCache statuses to match exactly (e.g. HIT,MISS,EXPIRED).
countrycomma listISO 3166 alpha-2 country codes (e.g. EE,DE).
edgeLocationstringEdge location / server zone, exact match.
remoteIpIPv4 or IPv6Filter by client IP. The match width adapts to the zone’s anonymization setting: exact when anonymization is disabled, /24 (IPv4) or /64 (IPv6) under last-octet anonymization, and ignored under full anonymization.
urlContainsstringCase-insensitive substring match against host + path.
userAgentContainsstringCase-insensitive substring match against the User-Agent header.
refererContainsstringCase-insensitive substring match against the Referer header.
searchspace-separatedFree-text token search. A row matches if ANY token appears in ANY searched column (cache status, request ID, edge location, host, path, user agent, referer, and content range for extended-logging zones). Max 16 tokens of up to 128 characters each.
includeOriginShieldbooleanInclude origin-shield (edge → shield) requests. Defaults to false.
limitintegerMaximum entries per page. Defaults to 100, capped at 10000.
offsetintegerNumber of entries to skip. Defaults to 0.
orderstringSort by timestamp: asc or desc (default).
Country code, the encrypted-at-rest authorization header, and the raw client IP are not matched by the free-text search parameter. Use country, remoteIp, and the dedicated header filters for those.

Response

200 OK returns a JSON envelope with the page of entries, pagination state, and an echoed query summary:
{
  "data": [
    {
      "timestamp": "2026-05-08T14:32:11.265Z",
      "pullZoneId": 1337,
      "requestId": "648fd832dbc1b102134949e15a9fdb2d",
      "cacheStatus": "MISS",
      "statusCode": 404,
      "bytesSent": 1095,
      "remoteIp": "163.172.53.0",
      "countryCode": "FI",
      "edgeLocation": "WA",
      "scheme": "https",
      "host": "example.b-cdn.net",
      "path": "/video.mp4",
      "url": "https://example.b-cdn.net/video.mp4",
      "userAgent": "Mozilla/5.0 ...",
      "referer": null
    }
  ],
  "pagination": {
    "offset": 0,
    "limit": 100,
    "returned": 1,
    "hasMore": false
  },
  "query": {
    "pullZoneId": 1337,
    "from": "2026-05-08T00:00:00Z",
    "to": "2026-05-09T00:00:00Z",
    "order": "desc"
  }
}

Log entry fields

FieldTypeDescription
timestampISO 8601 UTCTime the request was received at the edge (millisecond precision).
pullZoneIdintegerPull Zone identifier the request was served from.
requestIdstring32-character hex unique request identifier.
cacheStatusstringCache result (see cache status values below).
statusCodeintegerHTTP response status code.
bytesSentintegerTotal bytes sent in the response (headers + body).
remoteIpstring | nullClient IP, possibly anonymized; null when no IP was recorded.
countryCodestring | nullISO 3166 alpha-2 country code derived from the client IP; null if unknown.
edgeLocationstringPOP code that served the request.
schemestringhttp or https.
hoststringRequest Host header.
pathstringRequest URI path (with query string if present).
urlstringFully composed URL: {scheme}://{host}{path}.
userAgentstring | nullUser-Agent header; null when absent.
refererstring | nullReferer header; null when absent.

Extended logging fields

When extended logging is enabled for the Pull Zone (contact support), entries also include:
FieldTypeDescription
bodyBytesSentintegerResponse body bytes, excluding headers.
contentRangestring | nullHTTP Content-Range header.
authorizationHeaderstring | nullDecrypted Authorization header value (encrypted at rest).
Null fields are omitted from the JSON response.

Cache status values

ValueMeaning
HITResponse served directly from cache.
MISSResponse not in cache; fetched from origin.
BYPASSCache was skipped (e.g. due to request headers, cookies, or configuration).
REVALIDATEDCached response was validated with origin (e.g. via ETag / Last-Modified) and reused.
STALEStale cached response served (typically due to origin being unavailable or slow).
UPDATINGStale content served while a background cache update is in progress.
-No cache interaction (e.g. non-cacheable methods like POST).

Pagination

The response sets pagination.hasMore to true when more results are available beyond the current page. To fetch the next page, repeat the request with offset advanced by limit:
curl -H "AccessKey: your-api-key" \
     "https://logging.bunnycdn.com/v2/pullzones/1337/logs?from=...&to=...&limit=100&offset=100"

Error responses

Errors return a structured JSON envelope:
{
  "error": {
    "code": "invalid_request",
    "message": "One or more query parameters are invalid.",
    "details": [
      "Time range cannot exceed 3 days (log retention window).",
      "limit must be between 1 and 10000."
    ]
  }
}
HTTP statuserror.codeMeaning
400invalid_requestOne or more query parameters failed validation. See details.
401unauthorizedNeither Authorization nor AccessKey header was provided.
403forbiddenCredentials are invalid, or the Pull Zone is suspended/disabled.
404logging_disabledLogging is not enabled for this Pull Zone.
429rate_limitedPer-Pull-Zone rate limit exceeded (30 requests / 10 seconds).
500internal_errorUnexpected server error.

Logging API v1 (Legacy)

The v1 API is preserved for existing integrations. New work should use Logging API v2, which returns structured JSON, supports rich filtering and pagination, and avoids the pipe-injection issues inherent to the v1 format.
Download raw log files from the logging API:
GET https://logging.bunnycdn.com/{MM}-{DD}-{YY}/{pull_zone_id}.log
Authenticate with your account API key:
AccessKey: your-api-key
Use gzip compression to reduce download size:
Accept-Encoding: gzip
Example:
curl -H "AccessKey: your-api-key" \
     -H "Accept-Encoding: gzip" \
     "https://logging.bunnycdn.com/03-07-26/1337.log"

Query parameters

ParameterDescription
startNumber of log lines to skip from the beginning
endEnd index of log lines to return
sortSort order: asc or desc (default)
statusFilter by status codes: 2, 3, 4, 5 (e.g. 2,3,4,5 (default) or 2)
searchFilter log lines by string match
downloadWhether to return logs as a downloadable file (default: true)

Log format

Each request is stored as a pipe-separated line:
HIT|200|1507167062421|412|390|163.172.53.0|-|https://example.b-cdn.net/video.mp4|WA|Mozilla/5.0...|322b688bd63fb63f2babe9de30a5d262|DE
FieldDescription
Cache StatusCache result for the request. See cache status values.
Status CodeHTTP response code
TimestampUTC UNIX timestamp (milliseconds)
Bytes SentTotal bytes sent to client
Pull Zone IDID of the Pull Zone
Remote IPClient IP (anonymized by default)
RefererReferer header value
URLRequested URL
Edge LocationPOP code that served the request
User AgentClient user agent
Request IDUnique request identifier
Country CodeTwo-letter ISO country code
Pipe (|) characters in user-controllable fields (Referer, URL, User-Agent, Content-Range, Authorization) are stripped from the v1 output to keep the delimiter unambiguous. If you need the original byte sequence, use v2.

Extended logging

Extended logging adds three additional fields (contact support to enable):
FieldDescription
Body Bytes SentResponse body bytes (excluding headers)
Range HeaderHTTP Range header value
Authorization HeaderAuthorization header value (Encrypted at rest)

HTTP status codes

These codes apply to logged responses served by the CDN edge and are surfaced via both API versions.

2XX Success

CodeDescriptionExplanation
200OKRequest successful, content served
201CreatedRequest successful, new resource created
204No ContentRequest processed, no content to return
206Partial ContentPartial GET request fulfilled (e.g., video range request)

3XX Redirection

CodeDescriptionExplanation
301Moved PermanentlyURL permanently changed, use new location
302FoundURL temporarily moved
303See OtherResponse available at different location
304Not ModifiedCached content still valid, no transfer needed

4XX Client Errors

CodeDescriptionExplanation
400Bad RequestServer could not understand the request
401UnauthorizedAuthentication required
403ForbiddenServer refuses to fulfill request (hotlink protection, token auth)
404Not FoundFile not found
405Method Not AllowedRequest method not supported
410GoneResource no longer available
429Too Many RequestsRate limit exceeded
499Client Closed RequestClient terminated connection before response completed
A 499 status code appears in logs when a client closes the connection before the server finishes responding. This commonly occurs due to mobile network interruptions, ad blockers, or users navigating away. It’s normal and doesn’t indicate a server problem.

5XX Server Errors

CodeDescriptionExplanation
500Internal Server ErrorUnexpected server error
502Bad GatewayInvalid response from upstream server
503Service UnavailableServer temporarily overloaded or under maintenance
504Gateway TimeoutUpstream server didn’t respond in time
502 and 504 errors typically indicate the CDN edge nodes cannot reach your origin. Check if your origin firewall is blocking bunny.net IPs.