{"id":49353307,"url":"https://github.com/microlinkhq/screenshot-benchmark","last_synced_at":"2026-04-27T11:01:48.662Z","repository":{"id":344162619,"uuid":"1180684194","full_name":"microlinkhq/screenshot-benchmark","owner":"microlinkhq","description":"A terminal-based benchmark tool that races screenshot APIs against each other","archived":false,"fork":false,"pushed_at":"2026-04-15T18:38:14.000Z","size":55,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-15T20:30:12.849Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/microlinkhq.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2026-03-13T09:51:07.000Z","updated_at":"2026-04-15T18:38:18.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/microlinkhq/screenshot-benchmark","commit_stats":null,"previous_names":["microlinkhq/benchmarks","microlinkhq/screenshot-benchmark"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/microlinkhq/screenshot-benchmark","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microlinkhq%2Fscreenshot-benchmark","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microlinkhq%2Fscreenshot-benchmark/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microlinkhq%2Fscreenshot-benchmark/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microlinkhq%2Fscreenshot-benchmark/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/microlinkhq","download_url":"https://codeload.github.com/microlinkhq/screenshot-benchmark/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microlinkhq%2Fscreenshot-benchmark/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32333199,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T23:26:28.701Z","status":"online","status_checked_at":"2026-04-27T02:00:06.769Z","response_time":128,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2026-04-27T11:01:45.208Z","updated_at":"2026-04-27T11:01:48.653Z","avatar_url":"https://github.com/microlinkhq.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Screenshot API Benchmark\n\nA terminal-based benchmark tool that races screenshot APIs against each other, showing live progress bars and a ranked summary table.\n\n## Benchmark Results\n\n\u003e Last run: **March 2026** · 7 URLs · cold requests only (cache bypassed) · [View full results →](https://microlink.io/benchmarks/screenshot-api)\n\n### Summary — Average Cold Duration\n\n| Rank | Adapter | Avg Cold (ms) | vs Fastest |\n|:----:|---------|:-------------:|:----------:|\n| 1 | **Microlink** | **4,111.84** | — |\n| 2 | ScreenshotAPI | 5,915.71 | +43.9% |\n| 3 | ScreenshotMachine | 6,099.77 | +48.4% |\n| 4 | Urlbox | 7,334.22 | +78.4% |\n| 5 | ScreenshotOne | 7,711.14 | +87.5% |\n| 6 | ApiFlash | 9,463.20 | +130.1% |\n\n### Per-URL Cold Duration (ms)\n\n| URL | Microlink | ScreenshotAPI | ScreenshotMachine | Urlbox | ScreenshotOne | ApiFlash |\n|-----|----------:|:-------------:|:-----------------:|:------:|:-------------:|:--------:|\n| vercel.com *(1920px, full-page, jpeg)* | 6,361 | 6,143 | 9,791 | 14,953 | 12,695 | 14,233 |\n| example.com *(1280×800, png)* | 968 | 4,988 | 1,321 | 2,331 | 3,135 | 1,820 |\n| stripe.com *(393×852, jpeg)* | 3,217 | 5,614 | 3,167 | 3,679 | 5,678 | 5,900 |\n| screenshotone.com *(1920px, full-page, png)* | 5,474 | 6,805 | 12,404 | 14,976 | 12,139 | 9,802 |\n| news.ycombinator.com *(1440px, full-page, jpeg)* | 3,435 | 5,385 | 4,329 | 4,748 | 6,857 | 1,968 |\n| github.com/trending *(768×1024, png)* | 3,060 | 6,174 | 3,898 | 4,267 | 6,059 | 5,366 |\n| framer.com *(1920×1800, jpeg)* | 6,267 | 6,301 | 7,789 | 6,386 | 7,415 | 27,154 |\n| **Total** | **28.8 s** | **41.4 s** | **42.7 s** | **51.3 s** | **54.0 s** | **66.2 s** |\n\n## Quick start\n\n```bash\nnpm install\ncp .env.example .env   # add your API keys\nnode benchmark.js\n# or\nnpm start\n```\n\n## API keys\n\nConfigure keys in `.env`:\n\n| Variable | Required | Notes |\n|---|---|---|\n| `MICROLINK_API_KEY` | Yes | Adapter is skipped if missing. |\n| `SCREENSHOTONE_API_KEY` | Yes | Adapter is skipped if missing. |\n| `SCREENSHOTONE_SECRET_KEY` | No | Optional signing key. |\n| `SCREENSHOTMACHINE_API_KEY` | Yes | Adapter is skipped if missing. |\n| `SCREENSHOTMACHINE_SECRET_PHRASE` | No | Optional secret phrase for signed URLs. |\n| `SCREENSHOTAPI_API_KEY` | Yes | Adapter is skipped if missing. |\n| `URLBOX_API_KEY` | Yes | Adapter is skipped if missing. |\n| `URLBOX_API_SECRET` | Yes | Required alongside the API key. |\n| `APIFLASH_API_KEY` | Yes | Adapter is skipped if missing. |\n| `SCREENSHOTLAYER_API_KEY` | Yes | Excluded from default runs due to low free-plan concurrency. Run explicitly with `node benchmark.js screenshotlayer`. |\n| `THUMIO_API_KEY` | Yes | Adapter is skipped if missing. |\n\nThum.io docs note that `viewportWidth` and `fullpage` are only available on \"better\" plan, so captures may not exactly match `config.js` on lower plans.\n\n## Metrics\n\nEach URL is tested per adapter, measuring:\n\n- **Cold duration** — response time with cache bypassed (fresh render)\n- **Cached duration** — response time served from cache (only when `--cache` is passed)\n- **Image size** — bytes of the returned image\n- **Image quality** — sharpness score (Laplacian variance)\n\n## CLI options\n\n- **Adapter filter** — Pass one or more adapter slugs to run only those adapters:  \n  `node benchmark.js microlink screenshotone`  \n  Available slugs: `microlink`, `screenshotone`, `screenshotmachine`, `screenshotapi`, `urlbox`, `apiflash`, `screenshotlayer`, `thumio`.\n- **`--cache`** — Also measure cached response times. Without this flag, only cold (fresh) requests are made. Adapters that don't support cache measurement will return `null` for cached duration.\n- **`--savescreenshots`** — Save each captured image to `tmp/` (e.g. `vercel.com_1920x1080_microlink.jpeg`).\n- **`--showdetail`** — Print per-URL cold duration tables after the summary. When combined with `--cache`, also prints cached duration tables.\n\n## Output\n\nResults are saved to `results/benchmark-\u003ctimestamp\u003e.json` after each run. When you filter by adapters, the filename includes their slugs: `results/benchmark-microlink-screenshotone-\u003ctimestamp\u003e.json`.\n\n## Adding a new adapter\n\n1. Create a file in `adapters/`, e.g. `adapters/myapi.js`\n2. Export a default object with this interface:\n\n```js\nexport default {\n  name: 'MyAPI',\n  slug: 'myapi',\n  website: 'https://myapi.com',\n  requiresKey: true, // false if a free tier exists\n\n  async capture({ url, width, height, fullPage, format, quality, cache = false }) {\n    // Make cold request (cache bypassed)\n    // ...\n\n    let cachedDuration = null\n    if (cache) {\n      // Make cached request (cache enabled)\n    }\n\n    return {\n      coldDuration,    // ms\n      cachedDuration,  // ms or null if cache is false / not supported\n      imageBuffer,     // Buffer\n      imageSize        // bytes\n    }\n  }\n}\n```\n\n3. If `requiresKey: true`, set `MYAPI_API_KEY` in `.env`. The benchmark skips adapters whose key is missing.\n\nNo changes to the core benchmark code are needed.\n\n## File structure\n\n```\nadapters/\n  apiflash.js            # ApiFlash adapter\n  microlink.js           # Microlink adapter\n  screenshotapi.js       # ScreenshotAPI adapter\n  screenshotlayer.js     # ScreenshotLayer adapter\n  screenshotmachine.js   # ScreenshotMachine adapter\n  screenshotone.js       # ScreenshotOne adapter\n  thumio.js              # Thum.io adapter\n  urlbox.js              # Urlbox adapter\nresults/                 # JSON output (gitignored, created at runtime)\ntmp/                     # Saved screenshots when using --savescreenshots (gitignored)\nbenchmark.js             # Entry point, race UI, orchestration\nconfig.js                # TEST_URLS and shared configuration\n.env.example             # Documents all API keys\npackage.json             # ESM, all dependencies\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmicrolinkhq%2Fscreenshot-benchmark","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmicrolinkhq%2Fscreenshot-benchmark","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmicrolinkhq%2Fscreenshot-benchmark/lists"}