Nothing is uploaded. The PDF is assembled in your browser.
A4 is right when the PDF will be printed or filed with other documents. Sizing each page to its image is right for screenshots and scans, where white margins are just waste.
from PIL import Image
paths = ["one.jpg", "two.jpg", "three.jpg"]
pages = [Image.open(p).convert("RGB") for p in paths]
pages[0].save("out.pdf", save_all=True, append_images=pages[1:])
That is the whole thing. Pillow writes PDF but cannot read it, so this is a one way street. The convert("RGB") matters because an RGBA image fails here for the same reason it fails as JPEG.
pages[0].save("out.pdf", save_all=True, append_images=pages[1:], resolution=150.0)
The resolution decides how many pixels become an inch, so a 1500 pixel wide image at 150 is ten inches across. That is how you control the printed size without resampling anything.
import pathlib
from PIL import Image
paths = sorted(pathlib.Path("scans").glob("*.jpg"))
pages = [Image.open(p).convert("RGB") for p in paths]
pages[0].save("scans.pdf", save_all=True, append_images=pages[1:], resolution=150.0)
sorted is doing real work there. Files named page1, page2, page10 sort into the wrong order, so zero pad the numbers when you create them.
See format support for what else Pillow writes.