diff --git a/packages/playwright-core/src/cli/installActions.ts b/packages/playwright-core/src/cli/installActions.ts
index ee95b3e4f1428..18258da128dc4 100644
--- a/packages/playwright-core/src/cli/installActions.ts
+++ b/packages/playwright-core/src/cli/installActions.ts
@@ -87,7 +87,9 @@ export async function markDockerImage(dockerImageNameTemplate: string) {
   await writeDockerVersion(dockerImageNameTemplate);
 }
 
-export async function installBrowsers(args: string[], options: { withDeps?: boolean, force?: boolean, dryRun?: boolean, list?: boolean, shell?: boolean, noShell?: boolean, onlyShell?: boolean }) {
+export async function installBrowsers(args: string[], options: { withDeps?: boolean, force?: boolean, dryRun?: boolean, list?: boolean, shell?: boolean, noShell?: boolean, onlyShell?: boolean, progress?: boolean }) {
+  if (options.progress === false)
+    process.env.PLAYWRIGHT_DOWNLOAD_NO_PROGRESS = '1';
   if (isLikelyNpxGlobal()) {
     console.error(wrapInASCIIBox([
       `WARNING: It looks like you are running 'npx playwright install' without first`,
diff --git a/packages/playwright-core/src/cli/program.ts b/packages/playwright-core/src/cli/program.ts
index afb51d56bea57..7eac07ab0bd3c 100644
--- a/packages/playwright-core/src/cli/program.ts
+++ b/packages/playwright-core/src/cli/program.ts
@@ -80,7 +80,8 @@ export function decorateProgram(program: Command) {
       .option('--force', 'force reinstall of already installed browsers')
       .option('--only-shell', 'only install headless shell when installing chromium')
       .option('--no-shell', 'do not install chromium headless shell')
-      .action(async function(args: string[], options: { withDeps?: boolean, force?: boolean, dryRun?: boolean, list?: boolean, shell?: boolean, noShell?: boolean, onlyShell?: boolean }) {
+      .option('--no-progress', 'do not show download progress bars')
+      .action(async function(args: string[], options: { withDeps?: boolean, force?: boolean, dryRun?: boolean, list?: boolean, shell?: boolean, noShell?: boolean, onlyShell?: boolean, progress?: boolean }) {
         try {
           await installBrowsers(args, options);
         } catch (e) {
diff --git a/packages/playwright-core/src/server/registry/oopDownloadBrowserMain.ts b/packages/playwright-core/src/server/registry/oopDownloadBrowserMain.ts
index c0c25d3fd5f4f..06acef879795d 100644
--- a/packages/playwright-core/src/server/registry/oopDownloadBrowserMain.ts
+++ b/packages/playwright-core/src/server/registry/oopDownloadBrowserMain.ts
@@ -18,6 +18,7 @@ import fs from 'fs';
 import path from 'path';
 
 import { ManualPromise } from '@isomorphic/manualPromise';
+import { getAsBooleanFromENV } from '@utils/env';
 import { httpRequest } from '@utils/network';
 import { removeFolders } from '@utils/fileUtils';
 import { extractZip } from '@utils/third_party/extractZip';
@@ -48,6 +49,7 @@ function downloadFile(options: DownloadParams): Promise<void> {
   let downloadedBytes = 0;
   let totalBytes = 0;
   let chunked = false;
+  const reportProgress = !getAsBooleanFromENV('PLAYWRIGHT_DOWNLOAD_NO_PROGRESS');
 
   const promise = new ManualPromise<void>();
   httpRequest({
@@ -106,7 +108,7 @@ function downloadFile(options: DownloadParams): Promise<void> {
 
   function onData(chunk: string) {
     downloadedBytes += chunk.length;
-    if (!chunked)
+    if (!chunked && reportProgress)
       progress(downloadedBytes, totalBytes);
   }
 }
diff --git a/tests/installation/playwright-cli-install-should-work.spec.ts b/tests/installation/playwright-cli-install-should-work.spec.ts
index ea8d9ecea1f0b..20bbfc1aa5c78 100755
--- a/tests/installation/playwright-cli-install-should-work.spec.ts
+++ b/tests/installation/playwright-cli-install-should-work.spec.ts
@@ -65,6 +65,24 @@ test('install command should work', async ({ exec, checkInstalledSoftwareOnDisk
   }
 });
 
+test('install command should suppress progress bar with --no-progress', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/41099' } }, async ({ exec, checkInstalledSoftwareOnDisk }) => {
+  await exec('npm i playwright');
+  const result = await exec('npx playwright install chromium --no-progress');
+  expect(result).toHaveLoggedSoftwareDownload(['chromium', 'chromium-headless-shell', 'ffmpeg', ...extraInstalledSoftware]);
+  await checkInstalledSoftwareOnDisk(['chromium', 'chromium-headless-shell', 'ffmpeg', ...extraInstalledSoftware]);
+  expect(result).not.toContain('% of');
+  expect(result).not.toContain('■');
+});
+
+test('install command should suppress progress bar with PLAYWRIGHT_DOWNLOAD_NO_PROGRESS', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/41099' } }, async ({ exec, checkInstalledSoftwareOnDisk }) => {
+  await exec('npm i playwright');
+  const result = await exec('npx playwright install chromium', { env: { PLAYWRIGHT_DOWNLOAD_NO_PROGRESS: '1' } });
+  expect(result).toHaveLoggedSoftwareDownload(['chromium', 'chromium-headless-shell', 'ffmpeg', ...extraInstalledSoftware]);
+  await checkInstalledSoftwareOnDisk(['chromium', 'chromium-headless-shell', 'ffmpeg', ...extraInstalledSoftware]);
+  expect(result).not.toContain('% of');
+  expect(result).not.toContain('■');
+});
+
 test('install command should work with HTTPS_PROXY', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/36650' } }, async ({ exec, checkInstalledSoftwareOnDisk }) => {
   await exec('npm i playwright');
   const proxy = await TestProxy.create(8947 + test.info().workerIndex * 4);
