Skip to content

Instantly share code, notes, and snippets.

@v--
Last active May 2, 2026 22:52
Show Gist options
  • Select an option

  • Save v--/d87f71cd8736232bd3f66b55aefd21c8 to your computer and use it in GitHub Desktop.

Select an option

Save v--/d87f71cd8736232bd3f66b55aefd21c8 to your computer and use it in GitHub Desktop.
A script to rescale all pages of a PDF file that are larger than the given reference page.
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.10"
# dependencies = [
# "click (>= 7.0)",
# "pypdf (>= 6.0)",
# ]
# ///
import pathlib
import click
from pypdf import PdfReader, PdfWriter
class ScalePdfError(click.ClickException):
pass
@click.command(help='Scale all pages of a PDF file to match a target width.')
@click.argument('src', type=click.Path(exists=True, readable=True, dir_okay=False, resolve_path=True, path_type=pathlib.Path))
@click.option('-o', '--output', type=click.Path(exists=False, resolve_path=True, path_type=pathlib.Path), help='Output file path.')
@click.option('-w', '--width', 'ref_width', type=click.FloatRange(min=1.0), help='Manually set the target page width.')
@click.option('-r', '--ref', type=click.IntRange(min=1), help='Use the width of a reference page.')
@click.option('-v', '--verbose', is_flag=True, help='Display information for every page.')
@click.option('-i', '--inline', is_flag=True, help='Use the source file as a destination.')
@click.option('-f', '--force', is_flag=True, help='Overwrite the destination file if it exists.')
@click.version_option(version='2.0')
def scalepdf(
src: pathlib.Path,
output: pathlib.Path | None,
ref_width: float | None,
ref: int | None,
verbose: bool,
inline: bool,
force: bool,
) -> None:
reader = PdfReader(src)
if ref is not None:
if ref_width is not None:
raise ScalePdfError('Cannot specify both width and reference page')
if ref >= len(reader.pages):
raise ScalePdfError(f'Reference page {ref} not found')
ref_page = reader.pages[ref - 1]
ref_width = ref_page.user_unit * ref_page.mediabox[2]
elif ref_width is None:
raise ScalePdfError('No width nor reference page specified')
if output is None and not inline:
raise ScalePdfError('No output path given and the inline option is not activated')
if (
output and output.exists() and
not (force or click.confirm(f'File already exists: {output.as_posix()}. Overwrite?'))
):
return
writer = PdfWriter()
writer.clone_reader_document_root(reader)
if reader.metadata is not None:
writer.add_metadata(reader.metadata)
last_scaling_factor: float | None = None
for i, page in enumerate(writer.pages, start=1):
page_width = page.mediabox[2]
factor = round(ref_width / page_width, 3)
if factor != last_scaling_factor:
if factor == 1:
click.echo(f'Not using scaling starting at page {i}')
else:
click.echo(f'Using new scaling factor {100 * factor:.1f}% starting at page {i}')
last_scaling_factor = factor
if factor != 1:
if verbose:
click.echo(f'Scaling page {i} by {100 * factor:.1f}%')
page.scale_by(factor)
elif verbose:
click.echo(f'No need to rescale page {i}')
writer.write(output or src)
if __name__ == '__main__':
scalepdf()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment