{
  "schemaVersion": "1.0",
  "canonicalPage": "https://fileformat.co/ext/webp",
  "inspectorUrl": "https://fileformat.co/inspect",
  "spec": {
    "slug": "webp",
    "extension": ".webp",
    "aliases": [],
    "name": "WebP Image Container",
    "shortName": "WebP",
    "category": "media-3d",
    "tier": 1,
    "summary": "RIFF-based modern raster image container supporting lossy (`VP8 `), lossless (`VP8L`), and extended alpha/animated/EXIF (`VP8X`) bitstreams.",
    "technicalNotes": "CDN optimization proxies frequently transcode JPEGs into WebP on the fly while keeping `.jpg` URLs—causing desktop tools that trust file extensions to fail until Magic Bytes (`RIFF....WEBP`) are checked.",
    "mimeTypes": [
      "image/webp"
    ],
    "identifiers": {
      "pronomPuid": "fmt/566",
      "specUrl": "https://developers.google.com/speed/webp/docs/riff_container"
    },
    "binarySignature": {
      "endianness": "little",
      "magicBytes": [
        {
          "offset": 0,
          "hex": "52 49 46 46 ?? ?? ?? ?? 57 45 42 50",
          "ascii": "RIFF....WEBP",
          "description": "'RIFF' + 4-byte LE chunk size + 'WEBP' FourCC"
        }
      ],
      "containerFamily": "riff",
      "headerLayout": [
        {
          "offset": "0x00 - 0x03",
          "byteOffset": 0,
          "byteLength": 4,
          "lengthLabel": "4 B",
          "dataType": "char[4]",
          "fieldName": "riff_magic",
          "description": "ASCII 'RIFF'"
        },
        {
          "offset": "0x04 - 0x07",
          "byteOffset": 4,
          "byteLength": 4,
          "lengthLabel": "4 B",
          "dataType": "uint32_le",
          "fieldName": "riff_size",
          "description": "File size minus 8 bytes"
        },
        {
          "offset": "0x08 - 0x0B",
          "byteOffset": 8,
          "byteLength": 4,
          "lengthLabel": "4 B",
          "dataType": "char[4]",
          "fieldName": "webp_fourcc",
          "description": "ASCII 'WEBP'"
        },
        {
          "offset": "0x0C - 0x0F",
          "byteOffset": 12,
          "byteLength": 4,
          "lengthLabel": "4 B",
          "dataType": "char[4]",
          "fieldName": "first_chunk",
          "description": "'VP8 ', 'VP8L', or 'VP8X'"
        }
      ]
    },
    "securityProfile": {
      "riskLevel": "low",
      "allowsArbitraryCodeOrMacros": false,
      "xxeRisk": false,
      "polyglotPrependRisk": false,
      "pickleDeserializationRisk": false,
      "uploadValidationNotes": "Keep libwebp patched (>= 1.3.2, post CVE-2023-4863 Huffman heap overflow) and check both 0x00=='RIFF' and 0x08=='WEBP'."
    },
    "codeSnippets": {
      "python": "import struct, sys\nwith open(sys.argv[1], \"rb\") as f:\n    riff, size, webp, chunk = struct.unpack(\"<4sI4s4s\", f.read(16))\n    assert riff == b\"RIFF\" and webp == b\"WEBP\"\n    print(f\"WebP ({chunk.decode().strip()}), riff_size={size}B\")",
      "typescript": "export async function checkWebp(file: File) {\n  const b = new Uint8Array(await file.slice(0, 16).arrayBuffer());\n  const dec = new TextDecoder();\n  return dec.decode(b.subarray(0, 4)) === 'RIFF' && dec.decode(b.subarray(8, 12)) === 'WEBP';\n}",
      "rust": "use std::{fs::File, io::Read};\nfn main() -> std::io::Result<()> {\n    let mut b = [0u8; 16];\n    File::open(std::env::args().nth(1).expect(\"usage: <prog> <file>\"))?.read_exact(&mut b)?;\n    println!(\"{} / {}\", String::from_utf8_lossy(&b[0..4]), String::from_utf8_lossy(&b[8..12]));\n    Ok(())\n}",
      "go": "package main\nimport (\"fmt\"; \"io\"; \"os\")\nfunc main() {\n    f, err := os.Open(os.Args[1])\n    if err != nil {\n        fmt.Fprintln(os.Stderr, \"open:\", err)\n        os.Exit(1)\n    }\n    defer f.Close()\n    b := make([]byte, 16)\n    if _, err := io.ReadFull(f, b); err != nil {\n        fmt.Fprintln(os.Stderr, \"read:\", err)\n        os.Exit(1)\n    }\n    fmt.Printf(\"%s-%s chunk=%s\\n\", string(b[0:4]), string(b[8:12]), string(b[12:16]))\n}"
    },
    "relatedFormats": [
      "avif",
      "png",
      "jpg"
    ],
    "verifiedAt": "2026-11-14T16:09:03Z"
  },
  "samples": [
    {
      "id": "webp-minimal",
      "filename": "minimal-vp8x.webp",
      "variant": "minimal",
      "title": "Minimal RIFF WebP (64×64 Lossless)",
      "description": "Real WebP encoded by libwebp via Pillow — RIFF/WEBP container with decodable VP8L/VP8 payload.",
      "localPath": "/fixtures/v1/webp/minimal-vp8x.webp",
      "cdnUrl": "https://fileformat.co/fixtures/v1/webp/minimal-vp8x.webp",
      "sizeBytes": 58,
      "sha256": "297ca327517d16217664fbb2ab4e878a676db57b3050a92b5ab929259266ffde",
      "expectValid": true
    },
    {
      "id": "webp-realistic",
      "filename": "og-banner-1200x630.webp",
      "variant": "realistic",
      "title": "1200×630 WebP Social Card",
      "description": "Real 1200×630 lossy WebP from Pillow at quality 85 for OpenGraph-dimension checks.",
      "localPath": "/fixtures/v1/webp/og-banner-1200x630.webp",
      "cdnUrl": "https://fileformat.co/fixtures/v1/webp/og-banner-1200x630.webp",
      "sizeBytes": 60664,
      "sha256": "1cf094696041edb5cd955bf546811c69b1e8cdd5092cdfd765300849e2ceee2d",
      "expectValid": true
    },
    {
      "id": "webp-edge-case",
      "filename": "truncated-riff.webp",
      "variant": "edge-case",
      "title": "Truncated RIFF WebP Stream",
      "description": "WebP truncated inside the image payload — declared RIFF size exceeds available bytes, Pillow must raise.",
      "localPath": "/fixtures/v1/webp/truncated-riff.webp",
      "cdnUrl": "https://fileformat.co/fixtures/v1/webp/truncated-riff.webp",
      "sizeBytes": 50,
      "sha256": "6b6b3468c2e38c48255de9164388e169324215d8fe802e113b1b109f631deee3",
      "expectValid": false,
      "edgeCaseTag": "RIFF Size Mismatch"
    }
  ]
}