APNG Checker
Check if a PNG file is animated (APNG). Analyze animation frames, delays, loop count, and chunk structure with detailed binary inspection.
Drop a PNG file here or click to browse
Supports PNG & APNG files up to 200 MB
About
Not every PNG that claims to be animated actually is. The APNG format extends the standard PNG specification by embedding an Animation Control chunk (acTL) and Frame Control chunks (fcTL) alongside traditional IDAT data. A missing or malformed acTL chunk means the file will render as a static image in every browser, even if frame data exists. Misidentifying a static PNG as animated (or vice versa) causes rendering failures in web applications, broken CSS sprite sheets, and inflated file sizes with no visual payoff.
This tool performs byte-level binary inspection of the uploaded file. It validates the 8-byte PNG signature, iterates every chunk in the file, and checks for the presence and structural validity of acTL, fcTL, and fdAT chunks per the APNG specification. It reports frame count, loop count, per-frame delay (delay_numdelay_den), dispose and blend operations, and flags any structural anomalies. No data leaves your browser. The file is parsed entirely client-side using the ArrayBuffer API.
Formulas
A valid PNG file starts with an 8-byte magic signature that must match exactly:
Each chunk in a PNG file follows a fixed binary structure:
where Length is a big-endian unsigned 32-bit integer representing only the data field size (excluding type and CRC). The CRC is computed over Type + Data using the CRC-32 polynomial:
APNG detection requires locating an acTL chunk (Animation Control) positioned before the first IDAT chunk. The acTL contains:
where num_plays = 0 means infinite looping. Each frame's timing is defined in its fcTL chunk:
where if delay_den = 0, it is treated as 100 (i.e., delay is in hundredths of a second). The dispose_op field controls how the frame buffer is cleared: 0 = none, 1 = background, 2 = previous. The blend_op controls compositing: 0 = source, 1 = over.
Reference Data
| Chunk Type | Required | Purpose | Length (bytes) | Position Rule |
|---|---|---|---|---|
| IHDR | Yes (PNG) | Image header: width, height, bit depth, color type | 13 | Must be first chunk |
| acTL | Yes (APNG) | Animation Control: frame count, play count | 8 | Before first IDAT |
| fcTL | Yes (APNG) | Frame Control: dimensions, offsets, delay, dispose/blend ops | 26 | Before corresponding IDAT or fdAT |
| fdAT | Yes (APNG) | Frame Data: compressed image data for non-default frames | Variable | After its fcTL |
| IDAT | Yes (PNG) | Image data (default frame in APNG) | Variable | After IHDR |
| IEND | Yes (PNG) | Image trailer, marks end of file | 0 | Must be last chunk |
| PLTE | Conditional | Palette for indexed-color images | Variable | Before IDAT |
| tRNS | No | Transparency data | Variable | After PLTE |
| gAMA | No | Gamma correction value | 4 | Before IDAT |
| cHRM | No | Chromaticity coordinates | 32 | Before PLTE |
| sRGB | No | Standard RGB color space intent | 1 | Before PLTE |
| iCCP | No | ICC color profile | Variable | Before PLTE |
| tEXt | No | Text metadata (uncompressed) | Variable | Anywhere |
| zTXt | No | Compressed text metadata | Variable | Anywhere |
| iTXt | No | International text (UTF-8) | Variable | Anywhere |
| pHYs | No | Physical pixel dimensions (DPI) | 9 | Before IDAT |
| sBIT | No | Significant bits per channel | Variable | Before PLTE |
| bKGD | No | Default background color | Variable | After PLTE, before IDAT |
| hIST | No | Palette histogram | Variable | After PLTE |
| tIME | No | Last modification time | 7 | Anywhere |