induwara.lk
induwara.lkDocuments · Privacy-first

Rotate PDF pages

Rotate one page, a range, or every page of a PDF by 90°, 180°, or 270° — fully inside your browser, no signup, no upload. The page content stays byte-identical; only the page's /Rotate entry changes, so there is no quality loss.

By Induwara AshinsanaUpdated May 11, 2026
PDF Page RotatorIn-browser · no upload
Files stay on your device

Everything happens in your browser. Nothing is uploaded.

Built against the ISO 32000-2 §7.7.3.3 /Rotate contract, using pdf-lib for the page-object mutation. Header, EOF, and rotation cross-check verified 2026-05-11 — full source list in the "Sources & references" section below.

How it works

A PDF page object stores its rotation in a single inheritable entry named /Rotate (ISO 32000-2 §7.7.3.3). The value must be a multiple of 90, interpreted clockwise in degrees, defaulting to 0 when the entry is absent. Rotating a page does not require touching the page's content stream — the text, vectors, and images stay byte-identical; PDF readers apply the angle when drawing. That is why a one-line metadata edit can re-orient a 200 MB scanned book in milliseconds.

The rotation is performed by pdf-lib, an MIT-licensed pure-JavaScript PDF library. It is loaded dynamically when you press Rotate — until then the page bundle stays small. Inside the React component the flow is: PDFDocument.load(bytes) parses the source, doc.getPages() yields the page handles, and for every selected index we read page.getRotation().angle, add your delta, normalise to (sum % 360 + 360) % 360, and write it back with page.setRotation(degrees(next)).

Before pdf-lib runs, the tool performs four deterministic checks so the plan can be validated up front:

  1. Validate the source. Confirms the PDF MIME type, a non-zero size, and a per-file cap of 100.0 MB. The first 1 KB is scanned for the literal %PDF-n.m header (ISO 32000-2 §7.5.2), and the last 2 KB for the %%EOF terminator (§7.5.5). Files missing either are rejected with a specific message.
  2. Read the exact page count. pdf-lib parses the catalog and page tree and reports getPageCount(). That number is the ceiling for every page in your selection — out-of-bounds entries become inline errors before the rotation runs.
  3. Build a page selection. "All pages" expands to [1..total]. "Specific pages" parses a comma-separated expression — single pages, inclusive ranges, and open-ended ranges. The set is deduplicated and sorted so a page listed twice still rotates exactly once.
  4. Cross-check the rotation arithmetic. At component mount the lookup table applyRotationByTable[current][delta] is compared against the modulo formula for every (current, delta) pair in {0,90,180,270}² — twelve pairs in total. If any disagree the Rotate button is disabled. Two independent implementations agreeing is the verification floor: a bug in one is caught by the other.

For each selected page, the new rotation is (currentRotation + delta) mod 360. Pages outside the selection are not touched at all, so their /Rotateentry stays byte-identical and even round-trip-comparison tools see no diff. The output is serialised through pdf-lib's save() and offered as a Blob URL download.

Rotation is one step in a larger document-cleanup flow, and the sibling tools on this site follow the same in-browser, no-upload contract. If a scan arrived as separate files, stitch them with the PDF merger first, then rotate the combined file here. To pull a single mis-oriented page out before fixing it, use the PDF splitter. And because a /Rotate edit never re-rasterises the page, the output stays as small as the input — if you also need to shrink a heavy scan, the PDF compressor is the right next step rather than the rotator.

Worked examples

Fix a sideways scanned page

A 12-page document where the scanner captured page 7 in landscape — readers see it rotated 90° counter-clockwise. Apply a single 90° clockwise turn to page 7 only.

  1. Source: 12 pages · delta: 90° clockwise
  2. Selection (1): 7
  3. page 7: /Rotate 0° → 90°
  4. Pages 1-6 and 8-12 are untouched. Page 7's /Rotate goes from 0 to 90; viewers now show it upright. Byte streams unchanged.

Flip every page upside-down

A 4-page two-up booklet imposition exported as upside-down for back-side printing. A single 180° rotation across every page makes the file print correctly.

  1. Source: 4 pages · delta: 180° (flip)
  2. Selection (4): 1-4
  3. page 1: /Rotate 0° → 180°
  4. page 2: /Rotate 0° → 180°
  5. page 3: /Rotate 0° → 180°
  6. page 4: /Rotate 0° → 180°
  7. Every page's /Rotate becomes 180. 180° rotations are involutions: applying it twice returns to upright (180 + 180 = 360 = 0).

Restore upright on a pre-rotated page

A 5-page form where page 3 already has /Rotate 90 baked in by an earlier tool. Applying 270° clockwise (equivalent to one quarter turn counter-clockwise) restores it to upright.

  1. Source: 5 pages · delta: 90° counter-clockwise
  2. Selection (1): 3
  3. page 3: /Rotate 90° → 0°
  4. 90 + 270 = 360 ≡ 0 (mod 360). The cross-check table agrees: table[90][270] = 0. Page 3's underlying content stream is unchanged — only the /Rotate entry was rewritten.

Frequently asked questions

Sources & references

Related tools

Rate this tool
Be the first to rate

Comments & feedback

Spotted a bug or want an improvement? Tell us — our team reviews every comment, and good ideas get built. Comments are public and anonymous.

Found a bug, edge case, or want to suggest an improvement?

Email me at [email protected] — most fixes ship within 24 hours.