skip to content

When is passing custom args or an executablePath to Playwright's launch justified, and what do you take on by doing it?

level: principalimportance: nice to knowfreq 24%

answer

  1. Escape hatches, not configuration knobs
  2. Playwright already computed a default set
  3. One flag adds, another subtracts
  4. The cost is support, not syntax
  5. Revisit every flag at upgrade

basics

~20 s

Rarely, and only for a capability no supported option provides. Playwright computes a default argument set and supports the browsers it ships; every custom flag or foreign binary is a divergence your team owns, debugs and revisits at each upgrade.

solid answer

~40 s

`args` appends flags to the set Playwright already computes, and `ignoreDefaultArgs` removes them - either a list such as `['--mute-audio']` or `true` to drop them all. `executablePath` replaces the bundled binary entirely. Both are documented as use-at-your-own-risk, because Playwright's guarantees are calibrated to the browser builds it ships with the defaults it chooses. Legitimate uses are narrow: loading a Chromium extension, or a device or media flag no option exposes. Illegitimate ones are common - `--no-sandbox` is already passed unless you set `chromiumSandbox: true`, and branded Chrome or Edge is reached through `channel`, not through a hand-written path. What you take on is a divergence nobody else runs: a flag can break automation subtly, and each upgrade is a fresh question of whether the flag is still needed or still safe.

code

typescript · 9 lines
typescript
import { chromium } from '@playwright/test';

const browser = await chromium.launch({
  ignoreDefaultArgs: ['--mute-audio'],
  args: ['--use-fake-device-for-media-stream'],
});
const page = await browser.newPage();
await page.goto('https://staging.example.com/hotels/check-in');
await browser.close();

go deeper

for a junior

Know that args adds command-line flags to the browser and executablePath points at a different binary, and that neither is something you need for ordinary work.

for a middle

Explain that Playwright computes a default argument set, that ignoreDefaultArgs removes from it, and that the sandbox is already disabled unless you ask for it.

for a senior

Show that you can tell a justified flag from a copied one, and that you keep divergences documented in one place so they can be reviewed and removed later.

for a principal

Own the policy: which escape hatches the organisation permits, who reviews them, and how each one is revisited at every browser upgrade rather than living forever.

Two launch options let you take control away from Playwright: `args`, which adds command-line flags to the browser it starts, and `executablePath`, which replaces the browser binary altogether. Both are documented with an explicit warning, and the principal-level answer is about when the warning is worth accepting. ## What Playwright already does for you Playwright computes a default argument list for each browser and adjusts it to the options you set. Two consequences matter: - **The defaults are part of the contract.** Auto-waiting, screenshots, video and tracing are all calibrated to a browser started the way Playwright starts it. - **Some flags are already there.** Unless you pass `chromiumSandbox: true`, Playwright starts Chromium with the sandbox disabled - so adding `--no-sandbox` yourself changes nothing and signals a misunderstanding. `args` appends to that list. `ignoreDefaultArgs` subtracts from it: give it an array such as `['--mute-audio']` to drop specific flags, or `true` to drop the whole default set and take full responsibility for what remains. Some arguments are refused outright - passing `--user-data-dir` throws, telling you to use `launchPersistentContext()` instead, and an argument that names a page to open is rejected as well. ## When a custom flag is justified 1. **A capability with no option.** Loading a Chromium extension needs `--load-extension` and `--disable-extensions-except`, because there is no first-class option for it. 2. **A device or media behaviour the API does not expose**, such as a fake capture device for a flow that reads a document camera during guest check-in. 3. **A documented workaround** for a browser bug, with a link to the issue in a comment next to the flag. Everything else deserves a second look, and every one of the three should be re-examined when the browser is upgraded. ## When it is not justified - **Running branded Chrome or Edge.** That is what `channel` is for; a hand-written `executablePath` to a Chrome install is more fragile and less portable. - **Copying flags from a blog post.** `--disable-gpu`, `--no-sandbox` and friends usually address a problem someone else had, in a different environment, years ago. - **Working around a flaky test.** A rendering or timing flag hides a race the same way a fixed delay does. ## What you take on | Choice | What you inherit | |---|---| | A custom `args` flag | A configuration nobody upstream tests; failures reproduce only for you | | `ignoreDefaultArgs: true` | Every default Playwright would have set, now yours to maintain | | `executablePath` | A browser build outside the supported set, with no version guarantee | The cost is not the line of code, it is the **support surface**. When a click stops working in one environment, the divergent flag becomes a suspect in every investigation, and the person debugging it a year later has no way to know whether it is load-bearing. ## A policy that holds up 1. Prefer a supported option. If one exists, the flag is a bug in the plan. 2. Require a comment next to any flag naming what it enables and linking the issue or requirement that justifies it. 3. Keep the divergence in one place, not sprinkled through tests, so it is visible in review and countable. 4. Re-test the removal at each browser upgrade - flags added for old bugs long outlive the bugs. 5. For `executablePath`, prefer `channel` first, and if a specific binary is truly required, pin how it is provisioned so the run is reproducible rather than dependent on whatever is installed. ## How to talk about it in an interview The strong answer is not a list of flags; it is a stance. Say that the bundled browsers with default arguments are the configuration the tool guarantees, that `args` and `executablePath` are escape hatches with a real support cost, and that you allow them only for a capability nothing else provides - documented, centralised, and revisited at every upgrade. Then show the tell that you have actually used them: naming that `--no-sandbox` is already the default, or that `--user-data-dir` in `args` is rejected in favour of a persistent context, proves the point far better than any general principle.

  • A teammate adds --no-sandbox to args so the suite runs in a container. What do you say?
    That it is already the default: Playwright starts Chromium with the sandbox disabled unless chromiumSandbox is set to true. The flag adds a divergence with no effect, so remove it and look for the real cause of the container failure - usually a missing system dependency.
  • What is the difference between ignoreDefaultArgs: true and passing an array of flags?
    The array removes only the flags you name and leaves the rest of Playwright's computed defaults intact. Passing true drops the whole default set, so anything the browser needs to work with Playwright is now yours to supply and maintain.
  • When would executablePath be preferable to channel?
    Almost never for branded Chrome or Edge, which channel handles portably. It earns its place only when a specific build is required that no channel names - a locally built browser, or a binary provisioned by your own tooling - and then the provisioning must be pinned so runs stay reproducible.

saying these in an interview costs you the question

  • Adds --no-sandbox despite it already being the default
  • Uses executablePath to run branded Chrome instead of channel
  • Copies flag lists from blog posts without justification
  • Passes --user-data-dir in args rather than a persistent context
  • Treats ignoreDefaultArgs: true as a harmless tidy-up