{"id":13447017,"url":"https://github.com/microlinkhq/browserless","last_synced_at":"2026-03-06T12:04:21.366Z","repository":{"id":37602509,"uuid":"102619418","full_name":"microlinkhq/browserless","owner":"microlinkhq","description":"The headless Chrome/Chromium driver on top of Puppeteer. Take screenshots, generate PDFs, extract text and HTML with a production-ready API.","archived":false,"fork":false,"pushed_at":"2026-03-01T16:46:44.000Z","size":26352,"stargazers_count":1779,"open_issues_count":5,"forks_count":87,"subscribers_count":9,"default_branch":"master","last_synced_at":"2026-03-01T19:11:16.721Z","etag":null,"topics":["automation","browser-automation","chromium","lighthouse","pdf-generation","screenshot","web-crawler","web-scraping"],"latest_commit_sha":null,"homepage":"https://browserless.js.org","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/microlinkhq.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"custom":"https://microlink.io/#pricing"}},"created_at":"2017-09-06T14:34:06.000Z","updated_at":"2026-03-01T16:07:12.000Z","dependencies_parsed_at":"2026-01-30T10:10:18.427Z","dependency_job_id":null,"html_url":"https://github.com/microlinkhq/browserless","commit_stats":{"total_commits":1770,"total_committers":19,"mean_commits":93.15789473684211,"dds":"0.12937853107344632","last_synced_commit":"3f22a6f3d6bb9e486fd406a784bb10f47532f491"},"previous_names":["kikobeats/browserless"],"tags_count":662,"template":false,"template_full_name":null,"purl":"pkg:github/microlinkhq/browserless","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microlinkhq%2Fbrowserless","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microlinkhq%2Fbrowserless/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microlinkhq%2Fbrowserless/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microlinkhq%2Fbrowserless/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/microlinkhq","download_url":"https://codeload.github.com/microlinkhq/browserless/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microlinkhq%2Fbrowserless/sbom","scorecard":{"id":78569,"data":{"date":"2025-08-04","repo":{"name":"github.com/microlinkhq/browserless","commit":"05c7a1b0943b45e52ed53202f3a433113b0dc764"},"scorecard":{"version":"v5.2.1-28-gc1d103a9","commit":"c1d103a9bb9f635ec7260bf9aa0699466fa4be0e"},"score":2.7,"checks":[{"name":"Maintained","score":5,"reason":"6 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 5","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":0,"reason":"dangerous workflow patterns detected","details":["Warn: script injection with untrusted input ' github.head_ref ': .github/workflows/main.yml:32"],"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#dangerous-workflow"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#cii-best-practices"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/main.yml:1","Warn: no topLevel permission defined: .github/workflows/pull_request.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#binary-artifacts"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.md:0","Info: FSF or OSI recognized license: MIT License: LICENSE.md:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#license"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/microlinkhq/browserless/main.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/microlinkhq/browserless/main.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/main.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/microlinkhq/browserless/main.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:37: update your workflow using https://app.stepsecurity.io/secureworkflow/microlinkhq/browserless/main.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:38: update your workflow using https://app.stepsecurity.io/secureworkflow/microlinkhq/browserless/main.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:56: update your workflow using https://app.stepsecurity.io/secureworkflow/microlinkhq/browserless/main.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:58: update your workflow using https://app.stepsecurity.io/secureworkflow/microlinkhq/browserless/main.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/main.yml:62: update your workflow using https://app.stepsecurity.io/secureworkflow/microlinkhq/browserless/main.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/main.yml:71: update your workflow using https://app.stepsecurity.io/secureworkflow/microlinkhq/browserless/main.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/main.yml:82: update your workflow using https://app.stepsecurity.io/secureworkflow/microlinkhq/browserless/main.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pull_request.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/microlinkhq/browserless/pull_request.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pull_request.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/microlinkhq/browserless/pull_request.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pull_request.yml:31: update your workflow using https://app.stepsecurity.io/secureworkflow/microlinkhq/browserless/pull_request.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pull_request.yml:33: update your workflow using https://app.stepsecurity.io/secureworkflow/microlinkhq/browserless/pull_request.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/pull_request.yml:37: update your workflow using https://app.stepsecurity.io/secureworkflow/microlinkhq/browserless/pull_request.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/pull_request.yml:46: update your workflow using https://app.stepsecurity.io/secureworkflow/microlinkhq/browserless/pull_request.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/pull_request.yml:57: update your workflow using https://app.stepsecurity.io/secureworkflow/microlinkhq/browserless/pull_request.yml/master?enable=pin","Info:   0 out of  10 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   7 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#pinned-dependencies"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 12 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-15T05:19:44.745Z","repository_id":37602509,"created_at":"2025-08-15T05:19:44.745Z","updated_at":"2025-08-15T05:19:44.745Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30175918,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-06T11:48:51.886Z","status":"ssl_error","status_checked_at":"2026-03-06T11:48:51.460Z","response_time":250,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["automation","browser-automation","chromium","lighthouse","pdf-generation","screenshot","web-crawler","web-scraping"],"created_at":"2024-07-31T05:01:06.013Z","updated_at":"2026-03-06T12:04:21.321Z","avatar_url":"https://github.com/microlinkhq.png","language":"JavaScript","funding_links":["https://microlink.io/#pricing"],"categories":["JavaScript","others"],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg style=\"width: 500px; margin:3rem 0 1.5rem;\" src=\"https://github.com/microlinkhq/browserless/raw/master/static/logo-banner.png#gh-light-mode-only\" alt=\"browserless\"\u003e\n  \u003cimg style=\"width: 500px; margin:3rem 0 1.5rem;\" src=\"https://github.com/microlinkhq/browserless/raw/master/static/logo-banner-light.png#gh-dark-mode-only\" alt=\"browserless\"\u003e\n  \u003cbr\u003e\u003cbr\u003e\n  \u003ca href=\"https://microlink.io\"\u003e\u003cimg src=\"https://img.shields.io/badge/powered_by-microlink.io-blue?style=flat-square\u0026color=%23EA407B\" alt=\"Powered by microlink.io\"\u003e\u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/github/tag/microlinkhq/browserless.svg?style=flat-square\" alt=\"Last version\"\u003e\n  \u003ca href=\"https://coveralls.io/github/microlinkhq/browserless\"\u003e\u003cimg src=\"https://img.shields.io/coveralls/microlinkhq/browserless.svg?style=flat-square\" alt=\"Coverage Status\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.org/package/browserless\"\u003e\u003cimg src=\"https://img.shields.io/npm/dm/browserless.svg?style=flat-square\" alt=\"NPM Status\"\u003e\u003c/a\u003e\n  \u003cbr\u003e\u003cbr\u003e\n\u003c/div\u003e\n\n\u003e The headless Chrome/Chromium driver on top of [Puppeteer](https://github.com/GoogleChrome/puppeteer).\n- [Highlights](#highlights)\n- [Installation](#installation)\n- [Usage](#usage)\n- [The cloud API solution](#the-cloud-api-solution)\n- [CLI](#cli)\n- [Initializing a browser](#initializing-a-browser)\n  - [.constructor(options)](#constructoroptions)\n  - [.createContext(options)](#createcontextoptions)\n  - [.browser()](#browser)\n  - [.respawn()](#respawn)\n  - [.close()](#close)\n- [Built-in](#built-in)\n  - [.html(url, options)](#htmlurl-options)\n  - [.text(url, options)](#texturl-options)\n  - [.pdf(url, options)](#pdfurl-options)\n  - [.screenshot(url, options)](#screenshoturl-options)\n  - [.destroyContext(options)](#destroycontextoptions)\n  - [.getDevice(options)](#getdeviceoptions)\n  - [.evaluate(fn, gotoOpts)](#evaluatefn-gotoopts)\n  - [.goto(page, options)](#gotopage-options)\n  - [.context()](#context)\n  - [.withPage(fn, \\[options\\])](#withpagefn-options)\n  - [.page()](#page)\n- [Extended](#extended)\n  - [function](#function)\n  - [lighthouse](#lighthouse)\n  - [screencast](#screencast)\n- [Packages](#packages)\n- [FAQ](#faq)\n- [License](#license)\n\n---\n\n## Highlights\n\n- Compatible with Puppeteer API ([text](#texturl-options), [screenshot](#screenshoturl-options), [html](#htmlurl-options), [pdf](#pdfurl-options)).\n- Built-in [adblocker](#adblock) for canceling unnecessary requests.\n- Shell interaction via [Browserless CLI](#cli).\n- Easy [Google Lighthouse](#lighthouse) integration.\n- Automatic retry \u0026 error handling.\n- Sensible good defaults.\n\n## Installation\n\nYou can install it via npm:\n\n```bash\nnpm install browserless puppeteer --save\n```\n\n**Browserless** runs on top of [Puppeteer](https://github.com/GoogleChrome/puppeteer), so you need that installed to get started.\n\nYou can choose between [`puppeteer`](https://www.npmjs.com/package/puppeteer) and [`puppeteer-core`](https://www.npmjs.com/package/puppeteer-core) depending on your use case.\n\n## Usage\n\nHere is a complete example showcasing some **Browserless** capabilities:\n\n```js\nconst createBrowser = require('browserless')\nconst termImg = require('term-img')\n\n// First, create a browserless factory\n// This is similar to opening a browser for the first time\nconst browser = createBrowser()\n\n// Browser contexts are like browser tabs\n// You can create as many as your resources can support\n// Cookies/caches are limited to their respective browser contexts, just like browser tabs\nconst browserless = await browser.createContext()\n\n// Perform your required browser actions.\n// e.g., taking screenshots or fetching HTML markup\nconst buffer = await browserless.screenshot('http://example.com', {\n  device: 'iPhone 6'\n})\n\nconsole.log(termImg(buffer))\n\n// After your task is done, destroy your browser context\nawait browserless.destroyContext()\n\n// At the end, gracefully shutdown the browser process\nawait browser.close()\n```\n\nAs you can see, **Browserless** uses a single browser process, allowing you to create and destroy multiple browser contexts within that same process.\n\nIf you're already using Puppeteer in your project, you can layer **Browserless** on top simply by installing it.\n\nYou can also include additional **Browserless** [packages](#packages) to suit your specific needs, all of which work well with Puppeteer.\n\n## The cloud API solution\n\nIf you don’t want to manage that infrastructure, you can use the fully managed\n[Microlink API](https://microlink.io/docs/api/getting-started/overview).\n\nIt covers every **browserless** use case but automatically handles proxy rotation, paywalls, bot detection, and restricted platforms such as major social networks, while scaling on demand.\n\nPricing is pay-as-you-go and [starts for free](https://microlink.io/#pricing).\n\n## CLI\n\nUsing the **Browserless** command-line tool, you can interact with Browserless through a terminal window, or use it as part of an automated process:\n\n\u003cdiv style=\"margin: auto;\"\u003e\n  \u003cvideo poster=\"/static/cli.png\" loop=\"\" controls=\"\" src=\"https://github.com/microlinkhq/browserless/assets/2096101/5200b2c5-d930-40e7-b128-6d23a6974c28\" style=\"width: 100%;border-radius: 4px;\" autoplay=\"\"\u003e\u003c/video\u003e\n\u003c/div\u003e\n\nInstall [`@browserless/cli`](https://npm.im/@browserless/cli) globally using your favorite package manager:\n\n```\nnpm install -g @browserless/cli\n```\n\nThen run `browserless` in your terminal to see the list of available commands.\n\n## Initializing a browser\n\nInitializing **Browserless** creates a headless browser instance.\n\n```js\nconst createBrowser = require('browserless')\n\nconst browser = createBrowser({\n  timeout: 25000,\n  lossyDeviceName: true,\n  ignoreHTTPSErrors: true\n})\n```\n\nThis instance provides several high-level methods. \n\nFor example:\n\n```js\n// Call `createContext` to create a browser tab\nconst browserless = await browser.createContext({ retry: 2 })\n\nconst buffer = await browserless.screenshot('https://example.com')\n\n// Call `destroyContext` to close the browser tab.\nawait browserless.destroyContext()\n```\n\nThe browser keeps running until you explicitly close it:\n\n```js\n// At the end, gracefully shutdown the browser process\nawait browser.close()\n```\n\n### .constructor(options)\n\nThe `createBrowser` method supports [puppeteer.launch#options](https://github.com/puppeteer/puppeteer/blob/main/docs/api/puppeteer.launchoptions.md).\n\n**Browserless** provides additional options for creating a browser instance:\n\n##### defaultDevice\n\nSets your browser viewport to that of the specified device:\n\ntype: `string`\u003cbr/\u003e\ndefault: `'Macbook Pro 13'`\n\n##### lossyDeviceName\n\ntype: `boolean`\u003cbr/\u003e\ndefault: `false`\n\nAllows for a margin of error when setting the device name.\n\n```js\n\n// Initialize browser instance\nconst browser = require('browserless')({ lossyDeviceName: true });\n\n(async () =\u003e {\n    // Create context/tab\n    const tabInstance = await browser.createContext();\n\n    // Even if the device name is misspelled, the property will default to 'MacBook Pro'\n    console.log(tabInstance.getDevice({ device: 'MacBook Pro' }))\n    console.log(tabInstance.getDevice({ device: 'macbook pro 13' }))\n    console.log(tabInstance.getDevice({ device: 'MACBOOK PRO 13' }))\n    console.log(tabInstance.getDevice({ device: 'macbook pro' }))\n    console.log(tabInstance.getDevice({ device: 'macboo pro' }))\n})()\n```\n\nThe provided name will be resolved to closest matching device.\n\nThis comes in handy in situations where the device name is set by a third-party.\n\n##### mode\n\ntype: `string`\u003cbr/\u003e\ndefault: `launch`\u003cbr/\u003e\nvalues: `'launch'` | `'connect'`\n\nSpecifies if the browser instance should be spawned using [puppeteer.launch](https://github.com/puppeteer/puppeteer/blob/v5.5.0/docs/api.md#puppeteerlaunchoptions) or [puppeteer.connect](https://github.com/puppeteer/puppeteer/blob/v5.5.0/docs/api.md#puppeteerconnectoptions).\n\n##### timeout\n\ntype: `number`\u003cbr/\u003e\ndefault: `30000`\n\nChanges the default maximum navigation time.\n\n##### puppeteer\n\ntype: `Puppeteer`\u003cbr/\u003e\ndefault: `puppeteer`|`puppeteer-core`|`puppeteer-firefox`\n\nBy default, it automatically detects which libary is installed (thus either [puppeteer](https://www.npmjs.com/package/puppeteer) or [puppeteer-core](https://www.npmjs.com/package/puppeteer-core) based on your installed dependecies.\n\n### .createContext(options)\n\nAfter initializing the browser, you can create a browser context which is equivalent to opening a tab:\n\n```js\nconst browserless = await browser.createContext({\n  retry: 2\n})\n```\n\nEach browser context is isolated, thus cookies/cache stay within its corresponding browser contexts, just like browser tabs. Each context can be initialized with its own set of options.\n\n#### options\n\nAll of Puppeteer's [browser.createBrowserContext#options](https://pptr.dev/next/api/puppeteer.browsercontextoptions) are supported.\n\nBrowserless provides additional browser context options:\n\n##### retry\n\ntype: `number`\u003cbr/\u003e\ndefault: `2`\n\nThe number of retries that can be performed before considering a navigation as failed.\n\n### .browser()\n\nReturns the internal [Browser](https://github.com/puppeteer/puppeteer/blob/v10.0.0/docs/api.md#class-browser) instance.\n\n```js\nconst headlessBrowser = await browser.browser()\n\nconsole.log('My headless browser PID is', headlessBrowser.process().pid)\nconsole.log('My headless browser version is', await headlessBrowser.version())\n```\n\n### .respawn()\n\nRespawns the internal browser.\n\n```js\nconst getPID = promise =\u003e (await promise).process().pid\n\nconsole.log('Process PID:', await getPID(browser.browser()))\n\nawait browser.respawn()\n\nconsole.log('Process PID:', await getPID(browser.browser()))\n```\n\nThis method is an implementation detail, normally you don't need to call it.\n\n### .close()\n\nCloses the internal browser.\n\n```js\nconst { onExit } = require('signal-exit')\n// automatically teardown resources after\n// `process.exit` is called\nonExit(browser.close)\n```\n\n## Built-in\n\n### .html(url, options)\n\nSerializes the content of a target `url` into HTML.\n\n```js\nconst html = await browserless.html('https://example.com')\n\nconsole.log(html)\n// =\u003e \"\u003c!DOCTYPE html\u003e\u003chtml\u003e\u003chead\u003e…\"\n```\n\n#### options\n\nSee [browserless.goto](/#gotopage-options) for all the options and supported values.\n\n### .text(url, options)\n\nSerializes the content from the target `url` into plain text.\n\n```js\nconst text = await browserless.text('https://example.com')\n\nconsole.log(text)\n// =\u003e \"Example Domain\\nThis domain is for use in illustrative…\"\n```\n\n#### options\n\nSee [browserless.goto](/#gotopage-options) for all the options and supported values.\n\n### .pdf(url, options)\n\nGenerates the PDF version of a website behind a `url`.\n\n```js\nconst buffer = await browserless.pdf('https://example.com')\n\nconsole.log(`PDF generated in ${buffer.byteLength()} bytes`)\n```\n\n#### options\n\nThis method uses the following options by default:\n\n```js\n{\n  margin: '0.35cm',\n  printBackground: true,\n  scale: 0.65\n}\n```\n\nSee [browserless.goto](/#gotopage-options) for all the options and supported values.\n\nAlso, all of Puppeteer's [page.pdf](https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#pagepdfoptions) options are supported.\n\nAdditionally, you can setup:\n\n##### margin\n\ntype: `string` | `string[]`\u003cbr/\u003e\ndefault: `'0.35cm'`\n\nSets screen margins. Supported units include:\n\n- `px` for pixel.\n- `in` for inches.\n- `cm` for centimeters.\n- `mm` for millimeters.\n\nYou can set the margin properties by passing them in as an `object`:\n\n```js\nconst buffer = await browserless.pdf(url.toString(), {\n  margin: {\n    top: '0.35cm',\n    bottom: '0.35cm',\n    left: '0.35cm',\n    right: '0.35cm'\n  }\n})\n```\n\nIn case a single margin value is provided, this will be used for all sides:\n\n```js\nconst buffer = await browserless.pdf(url.toString(), {\n  margin: '0.35cm'\n})\n```\n\n### .screenshot(url, options)\n\nGenerates screenshots based on a specified `url`.\n\n```js\nconst buffer = await browserless.screenshot('https://example.com')\n\nconsole.log(`Screenshot taken in ${buffer.byteLength()} bytes`)\n```\n\n#### options\n\nThis method uses the following options by default:\n\n```js\n{\n  device: 'macbook pro 13'\n}\n```\n\nSee [browserless.goto](/#gotopage-options) for all the options and supported values.\n\nAlso, all of Puppeteer's [page.screenshot](https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#pagescreenshotoptions) options are supported.\n\nAdditionally, **Browserless** provides the following options:\n\n##### codeScheme\n\ntype: `string`\u003cbr/\u003e\ndefault: `'atom-dark'`\n\nWhenever the incoming response `'Content-Type'` is set to `'json'`, the JSON payload will be presented as a formatted JSON string, beautified using the provided `codeScheme` theme or by default `atom-dark`. \n\nThe color schemes is based on the [Prism library](https://prismjs.com).\n\n![](https://i.imgur.com/uFfviX7.png)\n\nThe [Prism repository](https://github.com/PrismJS/prism-themes/tree/master?tab=readme-ov-file#available-themes) offers a wide range of themes to choose from as well as a [CDN option](https://unpkg.com/browse/prismjs@1.29.0/themes).\n\n##### element\n\ntype: `string` \u003cbr/\u003e\n\nReturns the first instance of a matching DOM element based on a [CSS selector](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors). This operation remains unresolved until the element is displayed on screen or the specified maximum [timeout](#timeout) is reached.\n\n##### overlay\n\ntype: `object`\n\nOnce the screenshot has been taken, this option allows you to apply an overlay (backdrop).\n\n![Overlay example](/static/ml-landing.jpeg)\n\nYou can configure the overlay by specifying the following:\n\n- **browser**: Specifies the color of the browser stencil to use, thus either `light` or `dark` for light and dark mode respectively.\n- **background**: Specifies the background to use. A number of value types are supported:\n  - Hexadecimal/RGB/RGBA color codes, eg. `#c1c1c1`.\n  - [CSS gradients](https://developer.mozilla.org/en-US/docs/Web/CSS/gradient), eg. `linear-gradient(225deg, #FF057C 0%, #8D0B93 50%, #321575 100%)`\n  - Image URLs, eg. `https://source.unsplash.com/random/1920x1080`.\n\n```js\nconst buffer = await browserless.screenshot(url.toString(), {\n  styles: ['.crisp-client, #cookies-policy { display: none; }'],\n  overlay: {\n    browser: 'dark',\n    background:\n      'linear-gradient(45deg, rgba(255,18,223,1) 0%, rgba(69,59,128,1) 66%, rgba(69,59,128,1) 100%)'\n  }\n})\n```\n\n### .destroyContext(options)\n\nDestroys the current browser context.\n\n```js\nconst browserless = await browser.createContext({ retry: 0 })\n\nconst content = await browserless.html('https://example.com')\n\nawait browserless.destroyContext()\n```\n\n#### options\n\n##### force\n\ntype: `string` \u003cbr/\u003e\ndefault: `'force'`\n\nWhen `force` is set, it prevents the recreation of the context in case a browser action is being executed.\n\n### .getDevice(options)\n\nUsed to set a specific device type, this method sets the device properties.\n\n```js\nbrowserless.getDevice({ device: 'Macbook Pro 15' })\n\n// =\u003e {\n//   userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36',\n//   viewport: {\n//     width: 1440,\n//     height: 900,\n//     deviceScaleFactor: 2,\n//     isMobile: false,\n//     hasTouch: false,\n//     isLandscape: false\n//   }\n// }\n```\n\nThis method extends the [Puppeteer.KnownDevices](https://pptr.dev/api/puppeteer.knowndevices/) list by adding some missing devices.\n\n#### options\n\n##### device\n\ntype: `string` \u003cbr/\u003e\n\nThe device descriptor name. It's used to fetch preset values associated with a device.\n\nWhen [lossyDeviceName](#lossydevicename) is enabled, a fuzzy search is performed instead of a strict search to maximize the likelihood of finding a match.\n\n##### viewport\n\ntype: `object` \u003c/br\u003e\n\nSets extra viewport settings. These settings will be merged with the preset settings.\n\n```js\nbrowserless.getDevice({\n  device: 'iPad',\n  viewport: {\n    isLandscape: true\n  }\n})\n```\n\n##### headers\n\ntype: `object` \u003c/br\u003e\n\nExtra headers that will be merged with the device presets.\n\n```js\nbrowserless.getDevice({\n  device: 'iPad',\n  headers: {\n    'user-agent': 'googlebot'\n  }\n})\n```\n\n### .evaluate(fn, gotoOpts)\n\nIt exposes an interface for creating your own `evaluate` function, providing access to `page` and `response`.\n\nThe `fn` will receive `page` and `response` as arguments:\n\n```js\nconst ping = browserless.evaluate((page, response) =\u003e ({\n  statusCode: response.status(),\n  url: response.url(),\n  redirectUrls: response.request().redirectChain()\n}))\n\nawait ping('https://example.com')\n// {\n//   \"statusCode\": 200,\n//   \"url\": \"https://example.com/\",\n//   \"redirectUrls\": []\n// }\n```\n\nYou don't need to close the page, it will be closed automatically.\n\nInternally, the method performs a [browserless.goto](#gotopage-options), making it possible to pass extra arguments as a second parameter:\n\n```js\nconst serialize = browserless.evaluate(page =\u003e page.evaluate(() =\u003e document.body.innerText), {\n  waitUntil: 'domcontentloaded'\n})\n\nawait serialize('https://example.com')\n// =\u003e '\u003c!DOCTYPE html\u003e\u003chtml\u003e\u003cdiv\u003e…'\n```\n\n### .goto(page, options)\n\nPerforms a [page.goto](https://github.com/puppeteer/puppeteer/blob/main/docs/api/puppeteer.gotooptions.md) with a lot of extra capabilities:\n\n```js\nconst page = await browserless.page()\nconst { response, device } = await browserless.goto(page, { url: 'http://example.com' })\n```\n\n#### options\n\nAny option passed here will bypass to [page.goto](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagegotourl-options).\n\nAdditionally, you can setup:\n\n##### abortTypes\n\ntype: `array`\u003cbr/\u003e\ndefault: `[]`\n\nSets the ability to abort requests based on the [ResourceType](https://github.com/puppeteer/puppeteer/blob/3db7d55d261b1e1fead7228a7ebf9825a0bcbe72/packages/puppeteer-core/src/common/HTTPRequest.ts#L68).\n\n##### adblock\n\ntype: `boolean`\u003cbr/\u003e\ndefault: `true`\n\nEnables the built-in [adblocker by](https://www.npmjs.com/package/@cliqz/adblocker) [Cliqz](https://www.npmjs.com/package/@cliqz/adblocker) that aborts unnecessary third-party requests associated with ads services.\n\n##### animations\n\ntype: `boolean`\u003cbr/\u003e\ndefault: `false`\n\nDisables CSS [animations](https://developer.mozilla.org/en-US/docs/Web/CSS/animation) and [transitions](https://developer.mozilla.org/en-US/docs/Web/CSS/transition), also it sets [prefers-reduced-motion](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion) consequently.\n\n##### authenticate\n\ntype: `object`\u003cbr/\u003e\n\nIt will be passed down to [page.authenticate](https://pptr.dev/api/puppeteer.page.authenticate).\n\n##### click\n\ntype: `string` | `string[]`\u003cbr/\u003e\n\nClicks the DOM element matching the [CSS selector](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors).\n\n##### colorScheme\n\ntype: `string`\u003cbr/\u003e\ndefault: `'no-preference'`\n\nSets [prefers-color-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) CSS media feature, used to detect if the user has requested the system use a `'light'` or `'dark'` color theme.\n\n##### device\n\ntype: `string`\u003cbr/\u003e\ndefault: `'macbook pro 13'`\n\nIt specifies the [device](#devices) descriptor used to retrieve `userAgent` and `viewport`.\n\n##### headers\n\ntype: `object`\n\nAn object containing additional HTTP headers to send with every request.\n\n```js\nconst browserless = require('browserless')\n\nconst page = await browserless.page()\nawait browserless.goto(page, {\n  url: 'http://example.com',\n  headers: {\n    'user-agent': 'googlebot',\n    cookie: 'foo=bar; hello=world'\n  }\n})\n```\n\nThis sets [`visibility: hidden`](https://stackoverflow.com/a/133064/64949) on the matched elements.\n\n##### html\n\ntype: `string` \u003cbr/\u003e\n\nIn case you provide HTML markup, a [page.setContent](https://github.com/puppeteer/puppeteer/blob/v5.2.1/docs/api.md#pagesetcontenthtml-options) avoiding fetch the content from the target URL.\n\n##### javascript\n\ntype: `boolean`\u003cbr/\u003e\ndefault: `true`\n\nWhen it's `false`, it disables JavaScript on the current page.\n\n##### mediaType\n\ntype: `string`\u003cbr/\u003e\ndefault: `'screen'`\n\nChanges the CSS media type of the page using [page.emulateMediaType](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pageemulatemediamediatype).\n\n##### modules\n\ntype: `string` | `string[]`\u003c/br\u003e\n\nInjects [\u0026lt;script type=\"module\"\u0026gt;](https://v8.dev/features/modules) into the browser page.\n\nIt can accept:\n\n- Absolute URLs (e.g., `'https://cdn.jsdelivr.net/npm/@microlink/mql@0.3.12/src/browser.js'`).\n- Local file (e.g., `'local-file.js').\n- Inline code (e.g., `\"document.body.style.backgroundColor = 'red'\"`).\n\n```js\nconst buffer = await browserless.screenshot(url.toString(), {\n  modules: [\n    'https://cdn.jsdelivr.net/npm/@microlink/mql@0.3.12/src/browser.js',\n    'local-file.js',\n    \"document.body.style.backgroundColor = 'red'\"\n  ]\n})\n```\n\n##### onPageRequest\n\ntype:`function`\n\nAssociates a handler for every request in the page.\n\n##### scripts\n\ntype: `string` | `string[]`\u003c/br\u003e\n\nInjects [\u0026lt;script\u0026gt;](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script) into the browser page.\n\nIt can accept:\n\n- Absolute URLs (e.g., `'https://cdn.jsdelivr.net/npm/@microlink/mql@0.3.12/src/browser.js'`).\n- Local files (e.g., `'local-file.js').\n- Inline code (e.g., `\"document.body.style.backgroundColor = 'red'\"`).\n\n```js\nconst buffer = await browserless.screenshot(url.toString(), {\n  scripts: [\n    'https://cdn.jsdelivr.net/npm/jquery@3.4.1/dist/jquery.min.js',\n    'local-file.js',\n    \"document.body.style.backgroundColor = 'red'\"\n  ]\n})\n```\n\nUse [modules](#modules) whenever possible.\n\n##### scroll\n\ntype: `string`\n\nScrolls to the DOM element matching the [CSS selector](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors).\n\n##### styles\n\ntype: `string` | `string[]`\u003c/br\u003e\n\nInjects [\u0026lt;style\u0026gt;](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/style) into the browser page.\n\nIt can accept:\n\n- Absolute URLs (e.g., `'https://cdn.jsdelivr.net/npm/hack@0.8.1/dist/dark.css'`).\n- Local file (e.g., `'local-file.css').\n- Inline code (e.g., `\"body { background: red; }\"`).\n\n```js\nconst buffer = await browserless.screenshot(url.toString(), {\n  styles: [\n    'https://cdn.jsdelivr.net/npm/hack@0.8.1/dist/dark.css',\n    'local-file.css',\n    'body { background: red; }'\n  ]\n})\n```\n\n##### timezone\n\ntype: `string`\n\nChanges the [timezone](https://source.chromium.org/chromium/chromium/deps/icu.git/+/faee8bc70570192d82d2978a71e2a615788597d1:source/data/misc/metaZones.txt?originalUrl=https:%2F%2Fcs.chromium.org%2Fchromium%2Fsrc%2Fthird_party%2Ficu%2Fsource%2Fdata%2Fmisc%2FmetaZones.txt) of the page.\n\n##### url\n\ntype: `string`\n\nThe target URL.\n\n##### viewport\n\nSetups a custom viewport, using [page.setViewport](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagesetviewportviewport) method.\n\n##### waitForSelector\n\ntype:`string`\n\nWaits a quantity of time, selector or function using [page.waitForSelector](https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#pagewaitforselectorselector-options).\n\n##### waitForTimeout\n\ntype:`number`\n\nWaits a quantity time in milliseconds.\n\n##### waitUntil\n\ntype: `string` | `string[]`\u003cbr/\u003e\ndefault: `'auto'`\u003cbr/\u003e\nvalues: `'auto'` | `'load'` | `'domcontentloaded'` | `'networkidle0'` | `'networkidle2'`\n\nDetermines when the navigation is considered successful.\n\nIf an array of event strings is provided, navigation is considered successful once all events have fired.\n\nEvents can be either:\n\n- `'auto'`: A combination of `'load'` and `'networkidle2'` in a smart way to wait the minimum time necessary.\n- `'load'`: Consider navigation to be finished when the load event is fired.\n- `'domcontentloaded'`: Consider navigation to be finished when the DOMContentLoaded event is fired.\n- `'networkidle0'`: Consider navigation to be finished when there are no more than 0 network connections for at least 500 ms.\n- `'networkidle2'`: Consider navigation to be finished when there are no more than 2 network connections for at least 500 ms.\n\n### .context()\n\nReturns the [BrowserContext](https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#class-browsercontext) associated with your instance.\n\n```js\nconst browserContext = await browserless.context()\n\nconsole.log(browserContext.id)\n// =\u003e 'D2CD28FDECB1859772B9C5919E563C84'\n```\n\n### .withPage(fn, [options])\n\nReturns a higher-order function as convenient way to interact with a page:\n\n```js\nconst getTitle = browserless.withPage((page, goto) =\u003e async opts =\u003e {\n  const result = await goto(page, opts)\n  return page.title()\n})\n```\n\nThe function will be invoked in the following way:\n\n```js\nconst title = getTitle({ url: 'https://example.com' })\n```\n\n#### fn\n\ntype: `function`\n\nThe function to be executed. It receives `page, goto` as arguments.\n\n#### options\n\n##### timeout\n\ntype: `number`\u003c/br\u003e\ndefault: `browserless.timeout`\n\nThis setting will change the default maximum navigation time.\n\n### .page()\n\nReturns a standalone [Page](https://github.com/puppeteer/puppeteer/blob/ddc59b247282774ccc53e3cc925efc30d4e25675/docs/api.md#class-page) associated with the current browser context.\n\n```js\nconst page = await browserless.page()\nawait page.content()\n// =\u003e '\u003chtml\u003e\u003chead\u003e\u003c/head\u003e\u003cbody\u003e\u003c/body\u003e\u003c/html\u003e'\n```\n\n## Extended\n\n### function\n\nThe [`@browserless/function`](https://npm.im/@browserless/function) package provides an isolated VM scope to run arbitrary JavaScript code with runtime access to a browser page:\n\n```js\nconst createFunction = require('@browserless/function')\n\nconst code = async ({ page }) =\u003e page.evaluate('jQuery.fn.jquery')\n\nconst version = createFunction(code)\n\nconst { isFulfilled, isRejected, value } = await version('https://jquery.com')\n\n// =\u003e {\n//   isFulfilled: true,\n//   isRejected: false,\n//   value: '1.13.1'\n// }\n```\n\n#### options\n\nBesides the following properties, any other argument provided will be available during the code execution.\n\n##### vmOpts\n\nThe hosted code is also running inside a secure sandbox created via [vm2](https://npm.im/vm2).\n\n##### gotoOpts\n\nAny [goto#options](/#options-6) can be passed for tuning the internal URL resolution.\n\n### lighthouse\n\nThe [`@browserless/lighthouse`](https://npm.im/@browserless/lighthouse) package provides you the setup for running [Lighthouse](https://developers.google.com/web/tools/lighthouse) reports backed by browserless.\n\n```js\nconst createLighthouse = require('@browserless/lighthouse')\nconst createBrowser = require('browserless')\nconst { writeFile } = require('fs/promises')\nconst { onExit } = require('signal-exit')\n\nconst browser = createBrowser()\nonExit(browser.close)\n\nconst lighthouse = createLighthouse(async teardown =\u003e {\n  const browserless = await browser.createContext()\n  teardown(() =\u003e browserless.destroyContext())\n  return browserless\n})\n\nconst report = await lighthouse('https://microlink.io')\nawait writeFile('report.json', JSON.stringify(report, null, 2))\n```\n\nThe report will be generated for the provided URL. This extends the `lighthouse:default` settings. These settings are similar to the Google Chrome Audits reports on Developer Tools.\n\n#### options\n\nThe [Lighthouse configuration](https://github.com/GoogleChrome/lighthouse/blob/main/docs/configuration.md) that will extend `'lighthouse:default'` settings:\n\n```js\nconst report = await lighthouse(url, {\n  onlyAudits: ['accessibility']\n})\n```\n\nAlso, you can extend from a different preset of settings:\n\n```js\nconst report = await lighthouse(url, {\n  preset: 'desktop',\n  onlyAudits: ['accessibility']\n})\n```\n\nAdditionally, you can setup:\n\nThe lighthouse execution runs as a [worker thread](https://nodejs.org/api/worker_threads.html), any [worker#options](https://nodejs.org/api/worker_threads.html#new-workerfilename-options) are supported.\n\n##### logLevel\n\ntype: `string`\u003cbr/\u003e\ndefault: `'error'`\u003cbr/\u003e\nvalues: `'silent'` | `'error'` | `'info'` | `'verbose'` \u003c/br\u003e\n\nThe level of logging to enable.\n\n##### output\n\ntype: `string` | `string[]`\u003cbr/\u003e\ndefault: `'json'`\u003cbr/\u003e\nvalues: `'json'` | `'csv'` | `'html'`\n\nThe type(s) of report output to be produced.\n\n##### timeout\n\ntype: `number`\u003c/br\u003e\ndefault: `browserless.timeout`\n\nChanges the default maximum navigation time.\n\n### screencast\n\nThe [`@browserless/screencast`](https://npm.im/@browserless/screencast) package allows you to capture each frame of a browser navigation using puppeteer.\n\n\u003cdiv style=\"margin: auto;\"\u003e\n  \u003cvideo poster=\"/static/screencast.png\" loop=\"\" controls=\"\" src=\"https://github.com/microlinkhq/browserless/assets/2096101/a1753a2f-d4bb-47f1-a457-a0b73bb9d65d\" style=\"width: 100%;border-radius: 4px;\" autoplay=\"\"\u003e\u003c/video\u003e\n\u003c/div\u003e\n\nThis API is similar to [screenshots](#screenshoturl-options), but you have a more granular control over the frame and the output:\n\n```js\nconst createScreencast = require('@browserless/screencast')\nconst createBrowser = require('browserless')\n\nconst browser = createBrowser()\nconst browserless = await browser.createContext()\nconst page = await browserless.page()\n\nconst screencast = createScreencast(page, { \n  maxWidth: 1280, \n  maxHeight: 800 \n})\n\nconst frames = []\nscreencast.onFrame(data =\u003e frames.push(data))\n\nscreencast.start()\nawait browserless.goto(page, { url, waitForTimeout: 300 })\nawait screencast.stop()\n\nconsole.log(frames)\n```\n\nSee a [full example](/blob/master/packages/screencast/examples/server.js) that generates a GIF.\n\n#### page\n\ntype: `object`\n\nThe [Page](https://pptr.dev/api/puppeteer.page) object.\n\n#### options\n\nSee [Page.startScreencast](https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-startScreencast) to know all the options and values supported.\n\n## Packages\n\n**browserless** is internally divided into multiple packages, this way you only use code you need.\n\n| Package                                                                                               | Version                                                                                                                                     |\n| ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |\n| [browserless](https://github.com/microlinkhq/browserless/tree/master/packages/browserless)            | [![npm](https://img.shields.io/npm/v/browserless.svg?style=flat-square)](https://www.npmjs.com/package/browserless)                         |\n| [@browserless/benchmark](https://github.com/microlinkhq/browserless/tree/master/packages/benchmark)   | [![npm](https://img.shields.io/npm/v/@browserless/benchmark.svg?style=flat-square)](https://www.npmjs.com/package/@browserless/benchmark)   |\n| [@browserless/cli](https://github.com/microlinkhq/browserless/tree/master/packages/cli)               | [![npm](https://img.shields.io/npm/v/@browserless/cli.svg?style=flat-square)](https://www.npmjs.com/package/@browserless/cli)               |\n| [@browserless/devices](https://github.com/microlinkhq/browserless/tree/master/packages/devices)       | [![npm](https://img.shields.io/npm/v/@browserless/devices.svg?style=flat-square)](https://www.npmjs.com/package/@browserless/devices)       |\n| [@browserless/errors](https://github.com/microlinkhq/browserless/tree/master/packages/errors)         | [![npm](https://img.shields.io/npm/v/@browserless/errors.svg?style=flat-square)](https://www.npmjs.com/package/@browserless/errors)         |\n| [@browserless/examples](https://github.com/microlinkhq/browserless/tree/master/packages/examples)     | [![npm](https://img.shields.io/npm/v/@browserless/examples.svg?style=flat-square)](https://www.npmjs.com/package/@browserless/examples)     |\n| [@browserless/function](https://github.com/microlinkhq/browserless/tree/master/packages/function)     | [![npm](https://img.shields.io/npm/v/@browserless/function.svg?style=flat-square)](https://www.npmjs.com/package/@browserless/function)     |\n| [@browserless/goto](https://github.com/microlinkhq/browserless/tree/master/packages/goto)             | [![npm](https://img.shields.io/npm/v/@browserless/goto.svg?style=flat-square)](https://www.npmjs.com/package/@browserless/goto)             |\n| [@browserless/lighthouse](https://github.com/microlinkhq/browserless/tree/master/packages/lighthouse) | [![npm](https://img.shields.io/npm/v/@browserless/lighthouse.svg?style=flat-square)](https://www.npmjs.com/package/@browserless/lighthouse) |\n| [@browserless/pdf](https://github.com/microlinkhq/browserless/tree/master/packages/pdf)               | [![npm](https://img.shields.io/npm/v/@browserless/pdf.svg?style=flat-square)](https://www.npmjs.com/package/@browserless/pdf)               |\n| [@browserless/screencast](https://github.com/microlinkhq/browserless/tree/master/packages/screencast) | [![npm](https://img.shields.io/npm/v/@browserless/screencast.svg?style=flat-square)](https://www.npmjs.com/package/@browserless/screencast) |\n| [@browserless/screenshot](https://github.com/microlinkhq/browserless/tree/master/packages/screenshot) | [![npm](https://img.shields.io/npm/v/@browserless/screenshot.svg?style=flat-square)](https://www.npmjs.com/package/@browserless/screenshot) |\n\n## FAQ\n\n**Q: Why use `browserless` over `puppeteer`?**\n\n**browserless** does not replace Puppeteer; it complements it. It acts as a syntactic sugar layer over official Headless Chrome, optimized for production scenarios.\n\n**Q: Is there a hosted cloud solution?**\n\nYes. If you don't want to manage the infrastructure of headless browsers, proxies, and antibot workarounds, use the [Microlink API](https://microlink.io) we've built.\n\nIt scales on demand, and pricing [starts for free](https://microlink.io/#pricing).\n\n**Q: Why do you block ads scripts by default?**\n\nHeadless navigation is expensive compared to just fetching the content from a website.\n\nTo speed up the process, we block ad scripts by default because most of them are resource-intensive.\n\n**Q: My output is different from the expected**\n\n**Browserless** might have been too smart and blocked a request that you need.\n\nYou can activate debug mode using `DEBUG=browserless` environment variable in order to see what is happening under the hood:\n\nConsider opening an [issue](https://github.com/microlinkhq/browserless/issues/new) with the debug trace.\n\n**Q: I want to use `browserless` with my AWS Lambda like project**\n\nYes, check [chrome-aws-lambda](https://github.com/alixaxel/chrome-aws-lambda) to setup AWS Lambda with a binary compatible.\n\n## License\n\n**browserless** © [Microlink](https://microlink.io), released under the [MIT](https://github.com/microlinkhq/browserless/blob/master/LICENSE.md) License.\u003cbr\u003e\nAuthored and maintained by [Microlink](https://microlink.io) with help from [contributors](https://github.com/microlinkhq/browserless/contributors).\n\nThe [logo](https://thenounproject.com/term/browser/288309/) has been designed by [xinh studio](https://xinh.studio).\n\n\u003e [microlink.io](https://microlink.io) · GitHub [microlinkhq](https://github.com/microlinkhq) · X [@microlinkhq](https://x.com/microlinkhq)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmicrolinkhq%2Fbrowserless","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmicrolinkhq%2Fbrowserless","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmicrolinkhq%2Fbrowserless/lists"}