Issue Nº 41 — Sep 24, 2026

The header marks the job list private, but Cloudflare caches it anyway

Issue forty-one covers arbeitnow, a keyless job-board API in the Jobs category. This session queried it live. The cache header lets browsers keep a copy for five days, but the feed says jobs update every hour. The header also marks the response private, yet Cloudflare served a cached copy. The visa_sponsorship filter changes which jobs come back, but no job in the response has a visa_sponsorship field.

A private, five-day cache header on an hourly feed

This session sent GET https://www.arbeitnow.com/api/job-board-api with no query string. It returned 200, application/json, and access-control-allow-origin: *, about 1.9 MB of body across 250 jobs.

The response carried cache-control: private, max-age=432000. The max-age value is five days in seconds. The private directive limits that to the caller's own browser. It tells shared caches, such as a CDN, not to store the response.

Cloudflare stored it anyway. The same response carried cf-cache-status: HIT. Four reads on 2026-09-24 gave age values of 2962, 3578, 294, and 297 seconds. So each cached copy was between about 5 and 60 minutes old. This session did not measure how long Cloudflare keeps a copy.

The body's meta.info field says: "Jobs are updated every hour and order by the created_at timestamp." A browser that obeys the header can reuse one copy for five days. In that time, new jobs appear and old ones close. A client that needs current jobs should not trust the header. It should fetch the list again on its own schedule.

The visa filter changes results without a matching field in the response

This session compared GET .../job-board-api against GET .../job-board-api?visa_sponsorship=true. Both returned 250 jobs, but the first job in each list was different, and the two pages did not share the same set of job slugs.

None of the job objects in either response carry a field named visa_sponsorship, or any other field that states whether the employer sponsors a visa. The filter works on data the API holds server-side but never exposes in the job record.

A caller who wants to show why a job matched that filter has no field to point to. The only option is to trust the query parameter and not explain the match.

CORS preflight allows only GET and HEAD

This session sent OPTIONS to the job-board-api path. It returned HTTP 200, not 204, with allow: GET,HEAD and access-control-allow-origin: *.

That confirms the endpoint is read-only from a browser: no POST, PUT, or DELETE method is offered, matching an API with no write operations and no auth key to protect one.

The docs describe the same shape: one public GET endpoint, a page parameter, and a handful of filter parameters. There is no second endpoint for submitting a job.

Arbeitnow, by the numbers

Rendered live from the atlas entry
AuthenticationNone required
HTTPSSupported
CORSEnabled
PricingFree
FormatsJSON
Rate limit

Responses carry x-ratelimit-limit / x-ratelimit-remaining headers, but treat the numbers as advisory rather than as your own budget: the documented endpoint is served from a Cloudflare edge cache (cf-cache-status: HIT, Age up to ~32 minutes observed, despite Cache-Control: private), so calling the base URL verbatim returns whichever counters the edge captured on its last origin fetch. This run read a limit of 50 with 49 remaining on every response — cached and cache-missing alike — while an earlier probe of the same bare URL read 5 with 4 remaining, so the advertised cap itself is not stable across callers. The practical ceiling is Cloudflare's bot mitigation, not the header: bursts of uncached requests were cut off at the 8th and 10th call with HTTP 429, Cf-Mitigated: challenge, an HTML challenge body and no x-ratelimit headers at all.

job-boardeuroperemote-jobsno-auth

Sources

Facts checked Sep 2026