4Kwallpaper API
LIVE · KV + EDGE CACHE · NO STORAGE
Base: https://wp.luc.wtf

Data-forwarding proxy for client apps. Prefer mode=redirect for large downloads.

# 4kwallpaper API

Cloudflare Worker proxy for 4kwallpapers.com.

Forwards wallpaper metadata and download URLs to client apps with KV cache and edge cache headers. No object storage — data forwarding only.

Base URLhttps://wp.luc.wtf
Versionv1
AuthOptional X-API-Key (if API_KEY is configured)
CORSAccess-Control-Allow-Origin: *
SourceUpstream HTML + /search-api suggest endpoint

Live links: Health · Categories · Recent · This doc (HTML) · Raw Markdown


# Quick start

BASE=https://wp.luc.wtf

# Health
curl "$BASE/v1/health"

# Home feed
curl "$BASE/v1/wallpapers?feed=recent&page=1"

# Search
curl "$BASE/v1/search?q=goku"

# Detail (path from list item)
curl "$BASE/v1/wallpapers/nature/stac-a-phris-arch-26748"

# Download 4K (302 redirect to origin CDN)
curl -I "$BASE/v1/download/nature/stac-a-phris-arch-26748?resolution=3840x2160"

# Authentication

By default the API is open.

If the worker env var API_KEY is set, every request (except OPTIONS) must include:

X-API-Key: <your-key>

or

Authorization: Bearer <your-key>

Missing/invalid key → 401:

{ "error": "Unauthorized" }

# Caching

Responses include cache metadata so clients and CDNs behave well.

HeaderMeaning
Cache-Controlpublic, max-age=…, s-maxage=…, stale-while-revalidate=…
CDN-Cache-ControlEdge-oriented max-age
X-CacheHIT \MISS \BYPASS
X-Cache-Sourcekv \edge \origin

# Default TTLs (seconds)

DataEnv varDefault
Lists / feeds / categories pagesCACHE_TTL_LIST900
Wallpaper detailCACHE_TTL_DETAIL86400
Search resultsCACHE_TTL_SEARCH1800
Category catalogCACHE_TTL_CATEGORIES86400
SuggestCACHE_TTL_SUGGEST3600
Proxied imagesCACHE_TTL_IMAGE604800

Flow: Client → CF edge (Cache API / CDN) → Worker → KV (JSON) → 4kwallpapers.com


# Endpoints

# GET / · GET /docs

Human-readable HTML documentation (this page).

# GET /docs.md

Raw Markdown source (text/markdown).

# GET /v1 · GET /v1/openapi.json

Machine-readable endpoint map (JSON).

# GET /v1/health

Liveness probe.

Response 200

{
  "ok": true,
  "origin": "https://4kwallpapers.com",
  "time": "2026-07-20T17:37:30.309Z"
}

# GET /v1/categories

Catalog of primary categories and named feeds.

Response 200

{
  "categories": [
    { "slug": "anime", "name": "Anime", "path": "/anime/" },
    { "slug": "nature", "name": "Nature", "path": "/nature/" }
  ],
  "feeds": [
    { "slug": "recent", "name": "Recent", "path": "/" },
    { "slug": "popular", "name": "Popular", "path": "/most-popular-4k-wallpapers/" },
    { "slug": "featured", "name": "Featured", "path": "/best-4k-wallpapers/" },
    { "slug": "random", "name": "Random", "path": "/random-wallpapers/" }
  ]
}

Primary category slugs:

abstract · animals · anime · architecture · bikes · black-dark · cars · celebrations · cute · fantasy · flowers · food · games · gradients · graphics-cgi · lifestyle · love · military · minimal · movies · music · nature · people · photography · quotes · sci-fi · space · sports · technology · world


# GET /v1/wallpapers

List wallpapers from a named feed.

QueryTypeDefaultDescription
feedstringrecentrecent \popular \featured \random
pageint1Page number (≥ 1)

Example

GET /v1/wallpapers?feed=popular&page=2

Response 200 — see Paginated list


# GET /v1/categories/:slug

List wallpapers for a category or free-form tag page.

Param / queryDescription
sluge.g. anime, nature, scotland, goku
pagePage number (default 1)

Example

GET /v1/categories/anime?page=1
GET /v1/categories/scotland?page=1

Errors

  • 404 — empty first page for unknown slug

# GET /v1/search

Full-text / tag search (upstream search page).

QueryRequiredDescription
q or queryyesSearch string (spaces → hyphens upstream)
pagenoDefault 1

Example

GET /v1/search?q=goku&page=1

# GET /v1/search/suggest

Tag autocomplete (proxies upstream /search-api?action=tagsearch).

QueryRequired
q or queryyes

Example

GET /v1/search/suggest?q=goku

Response 200

{
  "query": "goku",
  "suggestions": [
    "Son Goku",
    "Goku",
    "Ultra Instinct Goku",
    "Goku Black"
  ]
}

# GET /v1/wallpapers/:category/:slugId

Wallpaper detail: tags, thumbnails, all resolutions, related items.

Path partExample
categorynature
slugIdstac-a-phris-arch-26748 (must end with -{numericId})

Example

GET /v1/wallpapers/nature/stac-a-phris-arch-26748

Response 200

{
  "id": 26748,
  "title": "Stac a Phris Arch Scotland",
  "category": "Nature",
  "categoryPath": "/nature/",
  "slug": "stac-a-phris-arch",
  "path": "/nature/stac-a-phris-arch-26748.html",
  "description": "Get this Cool Stac a Phris Arch background in 5120x3413 5K resolution…",
  "tags": ["Scotland", "Long exposure", "Sunset"],
  "keywords": ["Stac a Phris Arch", "Scotland", "5K"],
  "originalResolution": "5120x3413",
  "thumbnails": {
    "small": "https://4kwallpapers.com/images/walls/thumbs/26748.jpg",
    "medium": "https://4kwallpapers.com/images/walls/thumbs_2t/26748.jpg",
    "large": "https://4kwallpapers.com/images/walls/thumbs_3t/26748.jpg"
  },
  "resolutions": [
    {
      "width": 3840,
      "height": 2160,
      "label": "4K UHD",
      "group": "primary",
      "url": "https://4kwallpapers.com/images/wallpapers/stac-a-phris-arch-3840x2160-26748.jpg",
      "filename": "stac-a-phris-arch-3840x2160-26748.jpg"
    }
  ],
  "related": [],
  "sourceUrl": "https://4kwallpapers.com/nature/stac-a-phris-arch-26748.html"
}

# Resolution groups

groupDevices
primary4K + Original
desktop1080p → 5K, ultrawide
mobilePhone portrait sizes
tabletSquare tablet sizes
iphoneiPhone-specific
ipadiPad-specific
otherUnclassified fallback

# GET /v1/download/:category/:slugId

Resolve a wallpaper + resolution and either redirect or proxy the image.

QueryDefaultDescription
resolution or resbest 4K / firste.g. 3840x2160, 1080x1920
moderedirectredirect = 302 to origin · proxy = stream via worker

Examples

GET /v1/download/nature/stac-a-phris-arch-26748?resolution=3840x2160
GET /v1/download/nature/stac-a-phris-arch-26748?resolution=1080x1920&mode=proxy

mode=redirect302 + Location: https://4kwallpapers.com/images/wallpapers/...

mode=proxy200 image body with long Cache-Control (no storage; streamed).


# GET /v1/download

Query-style download helper.

QueryDescription
pathOrigin path, e.g. /nature/stac-a-phris-arch-26748.html
resolution / resTarget size
urlDirect origin image URL (must be /images/* on origin host)
moderedirect \proxy

Examples

GET /v1/download?path=/nature/stac-a-phris-arch-26748.html&resolution=3840x2160
GET /v1/download?url=https://4kwallpapers.com/images/wallpapers/….jpg&mode=proxy

# GET /v1/image

Thumbnail / image proxy. Only allows https://4kwallpapers.com/images/*.

GET /v1/image?url=https://4kwallpapers.com/images/walls/thumbs/26748.jpg

# Schemas

# Wallpaper list item

{
  "id": 26748,
  "title": "Stac a Phris Arch",
  "category": "nature",
  "slug": "stac-a-phris-arch",
  "path": "/nature/stac-a-phris-arch-26748.html",
  "tags": ["Scotland", "Long exposure", "Sunset"],
  "thumbnails": {
    "small": "https://4kwallpapers.com/images/walls/thumbs/26748.jpg",
    "medium": "https://4kwallpapers.com/images/walls/thumbs_2t/26748.jpg"
  },
  "sourceUrl": "https://4kwallpapers.com/nature/stac-a-phris-arch-26748.html"
}

Use category + slug + id (or path) for detail and download calls.

# Paginated list

{
  "items": [ /* Wallpaper list item */ ],
  "page": 1,
  "pageSize": 24,
  "totalPages": 950,
  "hasMore": true,
  "feed": "recent",
  "query": null,
  "category": null
}

totalPages may be null when upstream pagination is incomplete. Prefer hasMore for infinite scroll.

# Error

{
  "error": "Human-readable message",
  "available": ["1920x1080", "3840x2160"]
}
StatusWhen
400Bad params
401API key required/invalid
404Not found
405Method not allowed (only GET / OPTIONS)
500 / 502Worker or origin failure

# Client integration

# Flutter / mobile sketch

final base = 'https://wp.luc.wtf/v1';

// Feed
final feed = await http.get(Uri.parse('$base/wallpapers?feed=recent&page=1'));
final items = jsonDecode(feed.body)['items'] as List;

// Detail
final w = items.first;
final detail = await http.get(Uri.parse(
  '$base/wallpapers/${w['category']}/${w['slug']}-${w['id']}',
));

// Best phone wallpaper URL
final resolutions = jsonDecode(detail.body)['resolutions'] as List;
final phone = resolutions.firstWhere(
  (r) => r['width'] == 1080 && r['height'] == 1920,
  orElse: () => resolutions.first,
);

// Prefer redirect (lets OS/WebView hit origin CDN)
final downloadUrl =
  '$base/download/${w['category']}/${w['slug']}-${w['id']}'
  '?resolution=${phone['width']}x${phone['height']}';

# TypeScript sketch

const API = "https://wp.luc.wtf/v1";

const feed = await fetch(`${API}/wallpapers?feed=recent&page=1`).then((r) =>
  r.json(),
);

const w = feed.items[0];
const detail = await fetch(
  `${API}/wallpapers/${w.category}/${w.slug}-${w.id}`,
).then((r) => r.json());

const res4k =
  detail.resolutions.find(
    (r: { width: number; height: number }) =>
      r.width === 3840 && r.height === 2160,
  ) ?? detail.resolutions[0];

// Option A — open origin URL from detail (fastest)
window.open(res4k.url);

// Option B — go through API redirect
window.open(
  `${API}/download/${w.category}/${w.slug}-${w.id}?resolution=${res4k.width}x${res4k.height}`,
);
Device classPrefer
Desktop 4K3840x2160 (group: primary or desktop)
Desktop FHD1920x1080
Ultrawide3440x1440 / 2560x1080
Android FHD1080x1920
Android QHD1440x2560
iPhone 14/15/161179x2556
iPhone Pro Max1290x2796
Originalmatch originalResolution or group: primary “Original”

# Design notes

  1. No storage — Worker does not keep images in R2/Disk. Images are redirected or streamed.
  2. Upstream has no public JSON API — listings/detail are parsed from stable HTML; suggest uses /search-api.
  3. Prefer mode=redirect for full-size downloads so large files stay on the origin CDN.
  4. List items always include path / slug / id / category — detail URLs cannot be built from numeric id alone.
  5. Upstream markup may change — empty items or missing resolutions usually means a parser break.

# Rate limiting & fair use

This proxy is intended for a personal/client app. Respect Terms of Service and Copyright of 4kwallpapers.com. Do not hammer the origin; lean on the provided cache TTLs. Consider setting API_KEY before exposing the worker publicly.


# Deploy

pnpm install
pnpm deploy   # wrangler deploy
Binding / varPurpose
CACHE (KV)Parsed JSON cache
ORIGINUpstream base URL
API_KEYOptional gate
CACHE_TTL_*Tunable TTLs

Repo layout:

docs/API.md      ← this document (source of truth)
src/index.ts     ← router
src/parse.ts     ← HTML → JSON
src/cache.ts     ← KV + edge cache
src/origin.ts    ← upstream fetch + allowlist
wrangler.toml

# Changelog

VersionNotes
1.0.0Initial public API: feeds, categories, search, detail, download, KV + edge cache, online docs