{"id":18562505,"url":"https://github.com/root4loot/screener","last_synced_at":"2025-09-17T21:59:30.761Z","repository":{"id":203561977,"uuid":"709258531","full_name":"root4loot/screener","owner":"root4loot","description":"Take screenshots of webpages","archived":false,"fork":false,"pushed_at":"2025-02-24T14:46:46.000Z","size":611,"stargazers_count":9,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-24T15:52:15.776Z","etag":null,"topics":["aquatone","bugbounty","chromedp","go","golang","gowitness","pentesting","screenshot","web"],"latest_commit_sha":null,"homepage":"","language":"Go","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/root4loot.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","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}},"created_at":"2023-10-24T11:01:08.000Z","updated_at":"2025-03-06T08:27:41.000Z","dependencies_parsed_at":"2023-12-22T15:31:19.865Z","dependency_job_id":"b5c6412e-4ba4-4d48-9d2c-624222186eae","html_url":"https://github.com/root4loot/screener","commit_stats":null,"previous_names":["root4loot/screener"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/root4loot%2Fscreener","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/root4loot%2Fscreener/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/root4loot%2Fscreener/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/root4loot%2Fscreener/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/root4loot","download_url":"https://codeload.github.com/root4loot/screener/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248151105,"owners_count":21056024,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["aquatone","bugbounty","chromedp","go","golang","gowitness","pentesting","screenshot","web"],"created_at":"2024-11-06T22:09:55.968Z","updated_at":"2025-09-17T21:59:30.735Z","avatar_url":"https://github.com/root4loot.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./assets/logo.png\" alt=\"screener logo\" width=\"250\"/\u003e\n\u003c/p\u003e\n\n\u003cdiv align=\"center\"\u003e\n  A tool to capture screenshots of web pages using \u003ca href=\"https://github.com/go-rod/rod\"\u003eRod\u003c/a\u003e for headless browsing.\n\u003c/div\u003e\n\n\u003cbr\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://github.com/root4loot/screener/actions/workflows/build.yml\"\u003e\n    \u003cimg src=\"https://github.com/root4loot/screener/actions/workflows/build.yml/badge.svg?branch=main\" alt=\"\"/\u003e\n  \u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/twitter/follow/danielantonsen.svg?style=dark\" alt=\"Twitter Follow\"/\u003e\n\u003c/div\u003e\n\n## Features\n\n- Stream URLs from input.\n- Wait before capturing.\n- Follow or skip redirects.\n- Save unique screenshots only.\n- Handle many requests at once.\n- Ignore SSL errors.\n- Turn off HTTP/2 if needed.\n- Use a custom user agent.\n- Add URL to images.\n- Also screenshot 4xx/5xx error pages\n\n## Installation\n\n### Go\n\n```\ngo install github.com/root4loot/screener/cmd/screener@latest\n```\n\n### Docker\n\n```\ngit clone https://github.com/root4loot/screener.git\ncd screener\ndocker run --rm -it $(docker build -q .) -t example.com\n```\n\n## Usage\n\n```\nUSAGE:\n  screener [options] (-t \u003ctarget\u003e | -l \u003ctargets.txt\u003e)\n\nINPUT:\n  -t, --target                   target input (domain, IP, URL)\n  -l, --list                     input file with list of targets (one per line)\n\nCONFIGURATIONS:\n  -c,   --concurrency            number of concurrent operations                         (Default: 10)\n  -ad,  --avoid-duplicates       prevent saving duplicate outputs                        (Default: false)\n  -dt,  --duplicate-threshold    threshold for similarity percentage (0-100)             (Default: 96)\n                                 Applicable only when --avoid-duplicates is enabled. Outputs\n                                 with a similarity score greater than or equal to this value\n                                 will be considered duplicates and will not be saved.\n  -to,  --timeout                screenshot timeout                                      (Default: 15 seconds)\n  -ua,  --user-agent             specify user agent                                      (Default: Chrome UA)\n  -uh,  --use-http2              use HTTP2                                               (Default: false)\n  -nr,  --ignore-redirects       do not follow redirects                                 (Default: false)\n  -cw,  --capture-width          output width                                            (Default: 1366)\n  -ch,  --capture-height         output height                                           (Default: 768)\n  -cf,  --capture-full           capture entire content                                  (Default: false)\n  -dc,  --delay-capture          delay before operation (seconds)                        (Default: 2)\n  -dbc, --delay-between-capture  delay between operations (seconds)                      (Default: 0)\n  -rce, --respect-cert-err       respect certificate errors                              (Default: false)\n  -isc, --ignore-status-codes    ignore specific status codes (comma separated)          (Default: 204, 301, 302, 304, 401, 407)\n  -r,   --resolvers              custom DNS resolvers (comma separated)                  (Default: system resolvers)\n\nOUTPUT:\n  -o,   --outfolder              save outputs to specified folder                        (Default: ./screenshots)\n  -nt,  --no-text                do not add text to output images                        (Default: false)\n        --debug                  enable debug mode\n        --version                display version\n```\n\n## Example\n\n### Single Target\n\nCapture a single target. If you don't specify http or https, it defaults to https and tries http if https fails.\n\n```sh\n$ screener -t example.com\n[screener] (INF) Screenshot saved screenshots/https_example.com.png\n```\n\n### Multiple Targets\n\nCapture multiple targets.\n\n```sh\n$ cat targets.txt\n142.250.74.110\ngoogle.com\nbugcrowd.com\nhackerone.com/sitemap.xml\nhttp://example.com\nhttps://scanme.sh\n```\n\nNote that targets can be IP, domain, or full URL.\n\n```sh\n$ screener -l targets.txt\n[screener] (RES) Screenshot saved \"screenshots/https_google.com.png\"\n[screener] (RES) Screenshot saved \"screenshots/https_example.com.png\"\n[screener] (RES) Screenshot saved \"screenshots/https_142.250.74.110.png\"\n[screener] (RES) Screenshot saved \"screenshots/https_scanme.sh.png\"\n[screener] (RES) Screenshot saved \"screenshots/https_hackerone.com_sitemap.xml.png\"\n[screener] (RES) Screenshot saved \"screenshots/https_bugcrowd.com.png\"\n```\n\nYou may also \"stream\" targets to screener, capturing screenshots as they are received:\n\n```sh\n$ cat targets.txt | screener\n[screener] (RES) Screenshot saved screenshots/https_142.250.74.110.png\n[screener] (RES) Screenshot saved screenshots/https_google.com.png\n[screener] (RES) Screenshot saved screenshots/https_bugcrowd.com.png\n[screener] (RES) Screenshot saved screenshots/https_hackerone.com_sitemap.xml.png\n[screener] (RES) Screenshot saved screenshots/http_example.com.png\n[screener] (RES) Screenshot saved screenshots/https_scanme.sh.png\n```\n\nWhen dealing with many same-site URLs, use the `-su` or `--save-unique` flags to avoid saving multiple copies of the same screenshot. This makes it easier to sort through your screenshots!\nIn the following example, we're using [recrawl](https://github.com/root4loot/recrawl) to crawl a target site and pipe its results to screener with the `--save-unique` flag set. For more information, see [recrawl](https://github.com/root4loot/recrawl).\n\n```sh\n$ recrawl --target \"hackerone.com\" --hide-status --hide-media | screener --avoid-duplicates\n[recrawl] (RES) Hiding status code from output\n[recrawl] (RES) Excluding media [.png .jpg .jpeg .woff .woff2 .ttf .eot .svg .gif .ico .webp .mp4 .webm .mp3 .wav .flac .aac .ogg .m4a .flv .avi .mov .wmv .swf .mkv .m4v .3gp .3g2]\n[recrawl] (RES) Notice: Output is being piped. Results will be formatted accordingly.\n[screener] (RES) Screenshot saved screenshots/https_hackerone.com_robots.txt.png\n[screener] (RES) Screenshot saved screenshots/https_www.hackerone.com.png\n[screener] (RES) Screenshot saved screenshots/https_hackerone.com.png\n[screener] (RES) Screenshot saved screenshots/https_hackerone.com_assets_static_main_js-DsnehVnn.css.png\n[screener] (RES) Screenshot saved screenshots/https_hackerone.com_hacktivity_overview.png\n[screener] (RES) Screenshot saved screenshots/https_hackerone.com_leaderboard_all-time.png\n[screener] (RES) Screenshot saved screenshots/https_hackerone.com_users_sign_in.png\n[screener] (RES) Screenshot saved screenshots/https_hackerone.com_leaderboard.png\n[screener] (RES) Screenshot saved screenshots/https_hackerone.com_opportunities_all_search.png\n[screener] (RES) Screenshot saved screenshots/https_hackerone.com_assets_static_main_js-BQGA2x_6.js.png\n[screener] (RES) Screenshot saved screenshots/https_hackerone.com_assets_constants-06feb5198be5bd0ee51e0df3fedfd6d8ff1605a0e97a34becc0ec8615eda2e26.js.png\n[screener] (RES) Screenshot saved screenshots/https_hackerone.com_assets_static_main_css-B6Ng0SnZ.css.png\n[screener] (RES) Screenshot saved screenshots/https_hackerone.com_assets_static_pages-06310525d168da11de8f7941d231b4cae41abc6c58c72e6b4449e78fbfcb628e.css.png\n...\n```\n\n## Example Screenshot\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"./assets/example.png\" alt=\"screenshot example\"/\u003e\n\u003c/p\u003e\n\n## Tips\n\n- Use `-nu` or `--no-url` flag to remove the URL from the image.\n- Use `-ad` or `--avoid-duplicates` flag to prevent duplicate images from being saved.\n- macOS users can quickly access websites from screenshots: Press `Space` to preview an image, then mouse over the URL imprinted at the bottom. You can often click the link directly with `Command` + `Click`. If this method doesn't work, open the image in the Preview app to click the URL.\n\n## Library Example\n\n```\ngo get github.com/root4loot/screener/pkg/screener\n```\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"net/url\"\n\n\t\"github.com/root4loot/goutils/urlutil\"\n\t\"github.com/root4loot/screener/pkg/screener\"\n)\n\nfunc main() {\n\toptions := screener.NewOptions()\n\toptions.CaptureWidth = 1024\n\toptions.CaptureHeight = 768\n\t// more options ...\n\n\ts := screener.NewScreenerWithOptions(options)\n\n\turls := []string{\n\t\t\"https://example.com\",\n\t\t\"https://example.org\",\n\t\t\"https://scanme.sh\",\n\t}\n\n\tvar results []screener.Result\n\n\tfor _, u := range urls {\n\t\tparsedURL, err := url.Parse(u)\n\t\tif err != nil {\n\t\t\tfmt.Printf(\"Error parsing URL %s: %v\\n\", u, err)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Capture screenshot\n\t\tresult, err := s.CaptureScreenshot(parsedURL)\n\t\tif err != nil {\n\t\t\tfmt.Printf(\"Error capturing screenshot for %s: %v\\n\", u, err)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Check for duplicates\n\t\tif result.IsSimilarToAny(results, 96) { // 96% similarity\n\t\t\tfmt.Printf(\"Screenshot for %s is a duplicate, skipping\\n\", u)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Add text to image\n\t\torigin, err := urlutil.GetOrigin(result.TargetURL)\n\t\tif err != nil {\n\t\t\tfmt.Printf(\"Error getting origin for %s: %v\", result.TargetURL, err)\n\t\t\treturn\n\t\t}\n\n\t\tresult.Image, err = result.Image.AddTextToImage(origin)\n\t\tif err != nil {\n\t\t\tfmt.Printf(\"Error adding text to image for %s: %v\\n\", u, err)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Save image to file\n\t\tfilename, err := result.SaveImageToFolder(\"./screenshots\")\n\t\tif err != nil {\n\t\t\tfmt.Printf(\"Error saving screenshot for %s: %v\\n\", u, err)\n\t\t\tcontinue\n\t\t}\n\n\t\tfmt.Printf(\"Screenshot saved to %s\\n\", filename)\n\t\tresults = append(results, *result)\n\t}\n}\n\n```\n\nFor more, see [examples](https://github.com/root4loot/screener/tree/master/examples)\n\n## License\n\nSee [LICENSE](LICENSE)\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froot4loot%2Fscreener","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Froot4loot%2Fscreener","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froot4loot%2Fscreener/lists"}