{"id":13562675,"url":"https://github.com/cavaliergopher/grab","last_synced_at":"2025-12-14T23:56:33.788Z","repository":{"id":44889944,"uuid":"49065333","full_name":"cavaliergopher/grab","owner":"cavaliergopher","description":"A download manager package for Go","archived":false,"fork":false,"pushed_at":"2024-05-14T13:40:19.000Z","size":244,"stargazers_count":1460,"open_issues_count":33,"forks_count":151,"subscribers_count":17,"default_branch":"master","last_synced_at":"2025-10-27T18:08:40.669Z","etag":null,"topics":["download-manager","golang"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cavaliergopher.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"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":"2016-01-05T12:46:35.000Z","updated_at":"2025-10-16T09:40:57.000Z","dependencies_parsed_at":"2024-06-18T11:25:50.824Z","dependency_job_id":null,"html_url":"https://github.com/cavaliergopher/grab","commit_stats":{"total_commits":166,"total_committers":12,"mean_commits":"13.833333333333334","dds":"0.14457831325301207","last_synced_commit":"e06b719a377d74a18bdff0d0ffb9abf4a4afdbac"},"previous_names":["cavaliercoder/grab"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/cavaliergopher/grab","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cavaliergopher%2Fgrab","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cavaliergopher%2Fgrab/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cavaliergopher%2Fgrab/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cavaliergopher%2Fgrab/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cavaliergopher","download_url":"https://codeload.github.com/cavaliergopher/grab/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cavaliergopher%2Fgrab/sbom","scorecard":{"id":268148,"data":{"date":"2025-08-11","repo":{"name":"github.com/cavaliergopher/grab","commit":"e06b719a377d74a18bdff0d0ffb9abf4a4afdbac"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.8,"checks":[{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":6,"reason":"Found 9/15 approved changesets -- score normalized to 6","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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: BSD 3-Clause \"New\" or \"Revised\" License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/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 24 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-17T12:41:54.648Z","repository_id":44889944,"created_at":"2025-08-17T12:41:54.648Z","updated_at":"2025-08-17T12:41:54.648Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":27739697,"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","status":"online","status_checked_at":"2025-12-14T02:00:11.348Z","response_time":56,"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":["download-manager","golang"],"created_at":"2024-08-01T13:01:11.087Z","updated_at":"2025-12-14T23:56:33.758Z","avatar_url":"https://github.com/cavaliergopher.png","language":"Go","funding_links":[],"categories":["golang","Networking","Relational Databases","Go"],"sub_categories":["Transliteration","Uncategorized"],"readme":"# grab\n\n[![GoDoc](https://godoc.org/github.com/cavaliercoder/grab?status.svg)](https://godoc.org/github.com/cavaliercoder/grab) [![Build Status](https://travis-ci.org/cavaliercoder/grab.svg?branch=master)](https://travis-ci.org/cavaliercoder/grab) [![Go Report Card](https://goreportcard.com/badge/github.com/cavaliercoder/grab)](https://goreportcard.com/report/github.com/cavaliercoder/grab)\n\n*Downloading the internet, one goroutine at a time!*\n\n\t$ go get github.com/cavaliergopher/grab/v3\n\nGrab is a Go package for downloading files from the internet with the following\nrad features:\n\n* Monitor download progress concurrently\n* Auto-resume incomplete downloads\n* Guess filename from content header or URL path\n* Safely cancel downloads using context.Context\n* Validate downloads using checksums\n* Download batches of files concurrently\n* Apply rate limiters\n\nRequires Go v1.7+\n\n## Example\n\nThe following example downloads a PDF copy of the free eBook, \"An Introduction\nto Programming in Go\" into the current working directory.\n\n```go\nresp, err := grab.Get(\".\", \"http://www.golang-book.com/public/pdf/gobook.pdf\")\nif err != nil {\n\tlog.Fatal(err)\n}\n\nfmt.Println(\"Download saved to\", resp.Filename)\n```\n\nThe following, more complete example allows for more granular control and\nperiodically prints the download progress until it is complete.\n\nThe second time you run the example, it will auto-resume the previous download\nand exit sooner.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"time\"\n\n\t\"github.com/cavaliergopher/grab/v3\"\n)\n\nfunc main() {\n\t// create client\n\tclient := grab.NewClient()\n\treq, _ := grab.NewRequest(\".\", \"http://www.golang-book.com/public/pdf/gobook.pdf\")\n\n\t// start download\n\tfmt.Printf(\"Downloading %v...\\n\", req.URL())\n\tresp := client.Do(req)\n\tfmt.Printf(\"  %v\\n\", resp.HTTPResponse.Status)\n\n\t// start UI loop\n\tt := time.NewTicker(500 * time.Millisecond)\n\tdefer t.Stop()\n\nLoop:\n\tfor {\n\t\tselect {\n\t\tcase \u003c-t.C:\n\t\t\tfmt.Printf(\"  transferred %v / %v bytes (%.2f%%)\\n\",\n\t\t\t\tresp.BytesComplete(),\n\t\t\t\tresp.Size,\n\t\t\t\t100*resp.Progress())\n\n\t\tcase \u003c-resp.Done:\n\t\t\t// download is complete\n\t\t\tbreak Loop\n\t\t}\n\t}\n\n\t// check for errors\n\tif err := resp.Err(); err != nil {\n\t\tfmt.Fprintf(os.Stderr, \"Download failed: %v\\n\", err)\n\t\tos.Exit(1)\n\t}\n\n\tfmt.Printf(\"Download saved to ./%v \\n\", resp.Filename)\n\n\t// Output:\n\t// Downloading http://www.golang-book.com/public/pdf/gobook.pdf...\n\t//   200 OK\n\t//   transferred 42970 / 2893557 bytes (1.49%)\n\t//   transferred 1207474 / 2893557 bytes (41.73%)\n\t//   transferred 2758210 / 2893557 bytes (95.32%)\n\t// Download saved to ./gobook.pdf\n}\n```\n\n## Design trade-offs\n\nThe primary use case for Grab is to concurrently downloading thousands of large\nfiles from remote file repositories where the remote files are immutable.\nExamples include operating system package repositories or ISO libraries.\n\nGrab aims to provide robust, sane defaults. These are usually determined using\nthe HTTP specifications, or by mimicking the behavior of common web clients like\ncURL, wget and common web browsers.\n\nGrab aims to be stateless. The only state that exists is the remote files you\nwish to download and the local copy which may be completed, partially completed\nor not yet created. The advantage to this is that the local file system is not\ncluttered unnecessarily with addition state files (like a `.crdownload` file).\nThe disadvantage of this approach is that grab must make assumptions about the\nlocal and remote state; specifically, that they have not been modified by\nanother program.\n\nIf the local or remote file are modified outside of grab, and you download the\nfile again with resuming enabled, the local file will likely become corrupted.\nIn this case, you might consider making remote files immutable, or disabling\nresume.\n\nGrab aims to enable best-in-class functionality for more complex features\nthrough extensible interfaces, rather than reimplementation. For example,\nyou can provide your own Hash algorithm to compute file checksums, or your\nown rate limiter implementation (with all the associated trade-offs) to rate\nlimit downloads.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcavaliergopher%2Fgrab","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcavaliergopher%2Fgrab","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcavaliergopher%2Fgrab/lists"}