Playwright 1.63 Is 48MB. Trusted Publishing Is Still No

PyPI took playwright-1.63.0 on September 15. The manylinux wheel is 48.2MB and Trusted Publishing is No. Reproducible builds are still a Brett Cannon essay.

Your CI does not install “browser automation.” It downloads a blob.

On September 15, PyPI listed playwright-1.63.0. The manylinux x86_64 wheel is 48.2MB. The macOS 11 universal2 wheel is 44.3MB. Windows amd64 is 38.6MB. Windows ARM64 is 34.5MB. Linux aarch64 is 47.9MB. Next to the hashes is the line a lot of teams still do not read: Uploaded using Trusted Publishing? No.

Four days earlier, Real Python episode 311 spent a segment on what is still missing for reproducible builds on PyPI, walking through Brett Cannon’s argument that an independently verifiable, repeatable build of CPython and the tools around it is not a solved problem. The same show notes point at PEP 770 (SBOMs for packages) and Seth Michael Larson’s talk on phantom dependencies. That is the same week, not a coincidence of vibes. One is a 48MB browser driver. The other is the reason you cannot pretend the 48MB came from a monastery.

We already compared Playwright to Selenium and Browser Use. This is not another API tour. This is what your scheduler actually trusts at 2 a.m.

The wheel is the artifact

Playwright-the-pytest-plugin is a story you tell in stand-up. Playwright-the-wheel is a fat binary that drags browser machinery into a job runner. 48MB is not a crime. Unpinned 48MB is a habit.

The PyPI page publishes SHA256 for each file. The manylinux x86_64 digest in the extract is ad21bc07516b187965a7521c5cf0df0bd657b17482eaad74335272d35a2b07de. If your requirements.txt says playwright and your CI says pip install -r, you did not use that digest. You used a name.

“Uploaded via RestSharp/106.13.0.0” is in the file metadata. “Trusted Publishing? No” is in the same block. Trusted Publishing is the PyPI flow where the upload comes from a checked CI identity instead of a long-lived token in someone’s password manager. No does not mean the file is evil. No means the provenance story is thinner than the wheel.

If you automate screenshots, checkout flows, or internal admin clicks, this package is in the blast radius of every job that imports it. Treat it like you already treat secrets in pydantic-settings: an input, not scenery.

What episode 311 actually put on the table

The Django survey chunk on that episode is 3,500 developers and 40 countries. We already used that survey for the monolith piece. Skip it here.

The build chunk is the one that belongs next to Playwright. Cannon’s post, as the hosts summarize it, is about independently verifiable, repeatable builds of CPython and associated tools. Python is not there yet. The notes also mention a community response thread around Astral, a python/prebuilt-cpython repo, and a PSF prebuilt relocatable CPython effort. Those are interpreter-level moves. Your job still pip-installs a browser wheel that says Trusted Publishing No.

PEP 770 is about making packages measurable with SBOMs. Larson’s phantom-dependencies talk is about the requirements file that does not admit what it actually imports. Together they describe the gap: you can pin a version and still not know how the bytes were built, or which extra import your tool pulled in at runtime.

RISC-V becoming official in CPython, 3.15rc2, PEP 843, Guido on PEP 805 — those are the news ticker at the top of the same episode. They are not this article. They are a reminder that language releases and CI blobs move on different clocks. You can be meticulous about 3.15 wheels and sloppy about Playwright.

Pin, hash, cache, then run the browser

If the automation matters, pin playwright==1.63.0. Then pin the hash your platform actually downloads. pip’s hash-checking mode exists. So does uv’s lockfile. A floating minor version is how 1.63 becomes 1.64 in a Tuesday rerun you did not attend.

Cache the wheel in your own artifact store if you run this fifty times a day. PyPI as a live dependency at 2 a.m. is a network dependency dressed as a test. When PyPI hiccups, your “automation” is a queue of red dots.

playwright install still fetches browsers. That is a second supply channel. Pin browser revisions if the tool lets you. If it does not, snapshot the image. A job that installs Chromium from the internet on every run is not a flaky test. It is an unbounded one.

Do not run the browser job as root on a shared runner with cloud credentials in the environment “because it is just a screenshot.” The 48MB is code. Code executes.

We already wrote about subprocess and asyncio CLI automation. Same rule. The process you spawn has a filesystem and a network. Playwright’s process has a browser that will follow a URL. If the test environment can see production, the test is production.

A Monday checklist that is not a culture change

Print the PyPI files table for 1.63.0. Confirm Trusted Publishing is still No. If it flips to Yes later, good. Do not assume it did.

Add hashes to the lockfile. Fail the install when they mismatch. That failure is the point.

Put the browser install in the image build, not in the test step. The test step should be deterministic enough to bore you.

Log the wheel filename and digest at job start. When someone asks “what did we run in August,” you want a line in the log, not a shrug.

If you vendor Playwright inside an internal wrapper, SBOM that wrapper. PEP 770 is not a law you must obey tomorrow. It is the shape of the question purchasing will ask after the first incident.

If you cannot hash-pin because an internal mirror strips hashes, fix the mirror. That is the automation project. The screenshot script is the client.

What not to do with a 48MB jump

Do not treat a new Playwright minor as a reason to rewrite selectors. Read the changelog after you pin. Upgrade on a branch. Keep 1.62 in the lock until 1.63’s browsers behave on your pages.

Do not confuse “Microsoft signed something somewhere” with Trusted Publishing on PyPI. Different documents.

Do not paste the Ninth Circuit Copilot lede into this thread as if a court ruling hashes your wheel. Bloomberg Law reported September 16 that OpenAI and GitHub won a copyright suit over Copilot attribution at the Ninth Circuit. That is a training-data fight. It does not attest playwright-1.63.0. If your bot writes the selectors, you still review the selectors. The wheel is a separate trust problem.

Do not disable sandboxing to make a headless test green. Green and contained are different CI values.

A scheduler that buys a 48MB wheel every night is a supply chain. Call it that in the runbook. Pin the digest. Install the browser in the image. Leave Trusted Publishing set to No on the wiki until PyPI says otherwise. The test can wait 20 seconds for a page. It should not wait for an unsigned-in-this-sense blob from whoever had upload rights on a Monday in September.

Make the job image the source of truth

Most Playwright failures that look like “flakes” are environment drift. The runner pulled a newer Chromium. The OS image moved. A font vanished. Pinning 1.63.0 without pinning the browser layer is half a lockfile.

Build a container or a VM snapshot that already contains the 1.63.0 wheel and the browsers that version expects. Tag it with the date and the digest. Jobs should docker pull that tag, not pip install playwright from the public index. PyPI remains how you built the image, not how you run Tuesday.

If you cannot run containers, vendor the wheel into an internal index you control. Copy the SHA256 into the internal package page. When 1.64 lands, you choose the day. The scheduler does not choose it because a cache expired.

Hash-checking will annoy the first person who tries a drive-by upgrade. Good. That annoyance is cheaper than a red sprint after a silent browser bump broke checkout.

For local dev, match the image. Developers on 1.62 and CI on 1.63 is how you get “works on my machine” with extra steps. The 48MB download once per laptop is the fee. Paying it every morning is the bug.

If your automation is a cron on a laptop, the same rules shrink. Pin the version. Do not run pip install -U in the crontab. Log the version at start. When the laptop sleeps mid-run, that is a subprocess problem you already know. Wake is not a retry strategy.

Cannon’s reproducible-build essay is about CPython. You will not finish that essay this week. You can still stop treating a 48MB browser wheel as a floating name. That is the automation you can ship by Friday.

Keep a one-page runbook: version, digest, image tag, who is allowed to bump, what test must pass before the bump. When Trusted Publishing flips to Yes, add a screenshot of the PyPI badge to the page. Until then, the badge is No, and the runbook should say No in the same sentence as 1.63.0.

One more ugly detail from the files table: those Linux wheels are in the 48MB neighborhood because they carry platform payloads, not because your test file grew. Do not “optimize” by switching to an unofficial extra index that hosts a mystery build. If 48MB is too fat for the runner, you are on the wrong runner, or you should not be pulling browsers in the unit-test job. Split the suite. API tests stay thin. Browser tests use the fat image.

If a security questionnaire asks whether CI uses Trusted Publishing, answer with the PyPI page, not a feeling. Playwright 1.63.0 uploaded September 15, Trusted Publishing No. Write the date. When Microsoft or the maintainers change that bit, update the runbook the same day you bump the pin. Until that day, your automation’s trust story is hashes, an internal cache, and a human who is allowed to say no to pip install -U. That human should have a name on the runbook, not a group alias that nobody reads. Write the on-call rotation next to the digest. When the install fails a hash check at 2 a.m., that name is who gets the page, not the whole company Slack channel. If nobody owns the pin, the pin will drift by morning.

Spread The Article

Share this guide

Send this article to your network or keep a copy of the direct link.

X Facebook LinkedIn Reddit Telegram

Discussion

Leave a comment

No comments yet

Be the first to start the conversation.