{"id":45908830,"url":"https://github.com/rxvt/s3fetch","last_synced_at":"2026-02-28T04:57:18.617Z","repository":{"id":42472309,"uuid":"304999057","full_name":"rxvt/s3fetch","owner":"rxvt","description":"Simple multi-threaded S3 download tool.","archived":false,"fork":false,"pushed_at":"2026-02-21T08:35:54.000Z","size":586,"stargazers_count":30,"open_issues_count":3,"forks_count":6,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-21T11:11:16.873Z","etag":null,"topics":["aws","s3"],"latest_commit_sha":null,"homepage":"","language":"Python","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/rxvt.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2020-10-18T01:18:39.000Z","updated_at":"2026-02-21T06:52:58.000Z","dependencies_parsed_at":"2023-11-26T09:22:14.196Z","dependency_job_id":"64238140-6817-41da-9a2e-d7d95d66c849","html_url":"https://github.com/rxvt/s3fetch","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/rxvt/s3fetch","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rxvt%2Fs3fetch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rxvt%2Fs3fetch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rxvt%2Fs3fetch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rxvt%2Fs3fetch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rxvt","download_url":"https://codeload.github.com/rxvt/s3fetch/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rxvt%2Fs3fetch/sbom","scorecard":{"id":791612,"data":{"date":"2025-08-11","repo":{"name":"github.com/rxvt/s3fetch","commit":"692130e39c5b6a47d7e12760ccca43a72eb85043"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.4,"checks":[{"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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"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":"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":"Maintained","score":10,"reason":"30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","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":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Pinned-Dependencies","score":2,"reason":"dependency not pinned by hash detected -- score normalized to 2","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build-and-publish.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/rxvt/s3fetch/build-and-publish.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build-and-publish.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/rxvt/s3fetch/build-and-publish.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pre-commit.yml:12: update your workflow using https://app.stepsecurity.io/secureworkflow/rxvt/s3fetch/pre-commit.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pre-commit.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/rxvt/s3fetch/pre-commit.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/pre-commit.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/rxvt/s3fetch/pre-commit.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/rxvt/s3fetch/test.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/rxvt/s3fetch/test.yml/main?enable=pin","Warn: containerImage not pinned by hash: .devcontainer/Dockerfile:5","Warn: pipCommand not pinned by hash: .devcontainer/Dockerfile:24","Info:   0 out of   6 GitHub-owned GitHubAction dependencies pinned","Info:   2 out of   3 third-party GitHubAction dependencies pinned","Info:   0 out of   1 containerImage dependencies pinned","Info:   0 out of   1 pipCommand 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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/build-and-publish.yml:1","Warn: no topLevel permission defined: .github/workflows/pre-commit.yml:1","Info: topLevel 'contents' permission set to 'read': .github/workflows/test.yml:7","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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"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: MIT 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":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"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":"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":"Vulnerabilities","score":5,"reason":"5 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-79v4-65xg-pq4g","Warn: Project is vulnerable to: GHSA-cpwx-vrp4-4pq7","Warn: Project is vulnerable to: GHSA-9hjg-9r4m-mvj7","Warn: Project is vulnerable to: GHSA-pq67-6m6q-mj2v","Warn: Project is vulnerable to: GHSA-48p4-8xcf-vxj5"],"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-23T07:42:30.173Z","repository_id":42472309,"created_at":"2025-08-23T07:42:30.173Z","updated_at":"2025-08-23T07:42:30.173Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29685390,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-21T15:51:39.154Z","status":"ssl_error","status_checked_at":"2026-02-21T15:49:03.425Z","response_time":107,"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":["aws","s3"],"created_at":"2026-02-28T04:57:18.007Z","updated_at":"2026-02-28T04:57:18.611Z","avatar_url":"https://github.com/rxvt.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# S3Fetch\n\n\u003c!--toc:start--\u003e\n- [S3Fetch](#s3fetch)\n  - [Demo](#demo)\n  - [Features](#features)\n  - [Why use S3Fetch?](#why-use-s3fetch)\n  - [Installation](#installation)\n    - [Requirements](#requirements)\n    - [uv (recommended)](#uv-recommended)\n    - [pip](#pip)\n  - [Usage](#usage)\n  - [Examples](#examples)\n    - [Full example](#full-example)\n    - [Download all objects from a bucket](#download-all-objects-from-a-bucket)\n    - [Download objects with a specific prefix](#download-objects-with-a-specific-prefix)\n    - [Download objects to a specific directory](#download-objects-to-a-specific-directory)\n    - [Download multiple objects concurrently](#download-multiple-objects-concurrently)\n    - [Filter objects using regular expressions](#filter-objects-using-regular-expressions)\n  - [Troubleshooting](#troubleshooting)\n    - [Existing files are silently overwritten](#existing-files-are-silently-overwritten)\n    - [MacOS hangs when downloading using high number of threads](#macos-hangs-when-downloading-using-high-number-of-threads)\n\u003c!--toc:end--\u003e\n\nSimple \u0026 fast multi-threaded S3 download tool.\n\nSource: [https://github.com/rxvt/s3fetch](https://github.com/rxvt/s3fetch)\n\n![Build and Publish](https://github.com/rxvt/s3fetch/actions/workflows/build-and-publish.yml/badge.svg?branch=main)\n![Test](https://github.com/rxvt/s3fetch/actions/workflows/test.yml/badge.svg?branch=main)\n[![PyPI version](https://img.shields.io/pypi/v/s3fetch)](https://pypi.org/project/s3fetch/)\n\n## Demo\n\n![s3fetch demo](demo/demo.gif)\n\n## Features\n\n- Fast.\n- Simple to use.\n- Multi-threaded, allowing you to download multiple objects concurrently.\n- Quickly download a subset of objects under a prefix without listing all objects first.\n- Object listing occurs in a separate thread and downloads start as soon as the first object key is returned while the object listing completes in the background.\n- Filter list of objects using regular expressions.\n- Uses standard Boto3 AWS SDK and standard AWS credential locations.\n- List only mode if you just want to see what would be downloaded.\n- Implemented as a simple API you can use in your own projects.\n\n## Why use S3Fetch?\n\nTools such as the [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html) and [s4cmd](https://pypi.org/project/s4cmd/) are great and offer a lot of features, but S3Fetch out performs them when downloading a subset of objects from a large S3 bucket.\n\nS3Fetch begins downloading objects immediately while listing is still in progress, so you never wait for a full bucket listing before the first byte lands on disk. This makes a dramatic difference when your prefix matches a small subset of a bucket containing millions of objects.\n\n## Installation\n\n### Requirements\n\n- Python \u003e= 3.10\n- AWS credentials in one of the [standard locations](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html#cli-configure-files-where)\n\nS3Fetch is available on PyPI and can be installed via one of the following methods.\n\n### uv (recommended)\n\nEnsure you have [uv](https://docs.astral.sh/uv/) installed, then:\n\n`uv tool install s3fetch`\n\n### pip\n\n`pip3 install s3fetch`\n\n### Development Installation\n\nFor development work on S3Fetch:\n\n1. Clone the repository:\n   ```bash\n   git clone https://github.com/rxvt/s3fetch.git\n   cd s3fetch\n   ```\n\n2. Install [hatch](https://hatch.pypa.io/) using [uv](https://docs.astral.sh/uv/):\n   ```bash\n   uv tool install hatch --with hatch-pip-compile\n   ```\n\n3. Set up the development environment using Hatch:\n   ```bash\n   hatch env create\n   ```\n\n4. Run S3Fetch from source:\n   ```bash\n   hatch run s3fetch --help\n   ```\n\n5. (Optional) Populate a test S3 bucket with data for development:\n   ```bash\n   # First create your own test bucket (use a unique name!)\n   aws s3 mb s3://your-unique-s3fetch-test-bucket-name --region us-east-1\n\n   # Then populate it with test data\n   hatch run python scripts/populate_test_bucket.py --bucket your-unique-s3fetch-test-bucket-name --dry-run  # See what would be created\n   hatch run python scripts/populate_test_bucket.py --bucket your-unique-s3fetch-test-bucket-name           # Actually populate\n   ```\n\n## Usage\n\n```text\nUsage: s3fetch [OPTIONS] S3_URI\n\n  Concurrently download objects from S3 buckets.\n\n  Examples:\n\n    s3fetch s3://my-bucket/\n\n    s3fetch s3://my-bucket/photos/ --regex \".*\\.jpg$\"\n\n    s3fetch s3://my-bucket/data/ --dry-run --threads 10\n\nOptions:\n  --version                       Show the version and exit.\n  --region TEXT                   AWS region for the S3 bucket (e.g., us-\n                                  east-1, eu-west-1). Defaults to 'us-east-1'.\n  -d, --debug                     Enable verbose debug output.\n  --download-dir PATH             Local directory to save downloaded files.\n                                  Must already exist. Defaults to current\n                                  directory.\n  -r, --regex TEXT                Filter objects using regular expressions\n                                  (e.g., '.*\\.jpg$' for JPEG files).\n  -t, --threads INTEGER           Number of concurrent download threads\n                                  (minimum 1, warns above 1000). Defaults to\n                                  CPU core count.\n  --dry-run, --list-only          Show what would be downloaded without\n                                  actually downloading files.\n  --delimiter TEXT                Object key delimiter for path structure.\n                                  Defaults to '/'.\n  -q, --quiet                     Suppress all stdout; errors still go to\n                                  stderr. Mutually exclusive with --progress.\n  --progress [simple|detailed|live-update|fancy]\n                                  Progress display mode. 'simple' (default)\n                                  prints each object key as it downloads.\n                                  'detailed' adds a summary at the end.\n                                  'live-update' shows a real-time status line\n                                  and summary (no per-object output).\n                                  'fancy' shows a Rich progress bar and summary\n                                  (requires: pip install s3fetch[fancy]).\n  --help                          Show this message and exit.\n```\n\n## Examples\n\n### Full example\n\nDownload using 100 threads into `~/Downloads/tmp`, only downloading objects that end in `.dmg`.\n\n```text\n$ s3fetch s3://my-test-bucket --download-dir ~/Downloads/tmp/ --threads 100  --regex '\\.dmg$'\ntest-1.dmg...done\ntest-2.dmg...done\ntest-3.dmg...done\ntest-4.dmg...done\ntest-5.dmg...done\n```\n\n### Download all objects from a bucket\n\n```text\ns3fetch s3://my-test-bucket/\n```\n\n### Download objects with a specific prefix\n\nDownload all objects that start with `birthday-photos/2020-01-01`.\n\n```text\ns3fetch s3://my-test-bucket/birthday-photos/2020-01-01\n```\n\n### Download objects to a specific directory\n\nDownload objects to the `~/Downloads` directory.\n\n```text\ns3fetch s3://my-test-bucket/ --download-dir ~/Downloads\n```\n\n### Download multiple objects concurrently\n\nDownload 100 objects concurrently.\n\n```text\ns3fetch s3://my-test-bucket/ --threads 100\n```\n\n### Filter objects using regular expressions\n\nDownload objects ending in `.dmg`.\n\n```text\ns3fetch s3://my-test-bucket/ --regex '\\.dmg$'\n```\n\n## Library Usage\n\nS3Fetch can be used as a library in your Python projects.\n\n### Basic Library Usage\n\n```python\nfrom s3fetch import download\n\nsuccess_count, failures = download(\"s3://my-bucket/data/2023/\")\n\nprint(f\"Downloaded {success_count} objects successfully\")\nif failures:\n    print(f\"{len(failures)} objects failed to download\")\n```\n\n### Common Options\n\n```python\nfrom s3fetch import download\n\nsuccess_count, failures = download(\n    \"s3://my-bucket/data/\",\n    download_dir=\"./downloads\",   # local destination (default: cwd)\n    regex=r\"\\.csv$\",              # only download .csv files\n    threads=20,                   # concurrent downloads (default: CPU count)\n    dry_run=False,                # set True to list without downloading\n)\n```\n\n### Configuring Logging\n\nWhen using S3Fetch as a library, you can configure its logging behavior:\n\n```python\nimport logging\n\n# Option 1: Reduce S3Fetch output\nlogging.getLogger(\"s3fetch\").setLevel(logging.WARNING)\n\n# Option 2: Disable S3Fetch logging completely\nlogging.getLogger(\"s3fetch\").disabled = True\n```\n\n### Progress Tracking\n\n```python\nfrom s3fetch import download\nfrom s3fetch.utils import ProgressTracker\n\ntracker = ProgressTracker()\nsuccess_count, failures = download(\n    \"s3://my-bucket/data/\",\n    progress_tracker=tracker,\n)\n\nstats = tracker.get_stats()\nprint(f\"Found:      {stats['objects_found']} objects\")\nprint(f\"Downloaded: {stats['objects_downloaded']} objects\")\nprint(f\"Total size: {stats['bytes_downloaded'] / (1024 * 1024):.1f} MB\")\nprint(f\"Speed:      {stats['download_speed_mbps']:.2f} MB/s\")\n```\n\nThe `ProgressTracker` is thread-safe and can be polled from a separate thread\nfor real-time updates while `download()` is running.\n\n### Advanced Usage — Custom boto3 Client\n\nPass a pre-built boto3 client to use a custom session, role, or region:\n\n```python\nimport boto3\nfrom s3fetch import download\n\nsession = boto3.Session(profile_name=\"production\")\nclient = session.client(\"s3\", region_name=\"us-west-2\")\n\nsuccess_count, failures = download(\n    \"s3://my-bucket/data/\",\n    client=client,\n)\n```\n\n### Download Callbacks\n\nUse the `on_complete` parameter to receive a callback for each successfully\ndownloaded object:\n\n```python\nfrom s3fetch import download\n\ndef on_object_complete(key: str) -\u003e None:\n    print(f\"Finished: {key}\")\n\nsuccess_count, failures = download(\n    \"s3://my-bucket/data/\",\n    on_complete=on_object_complete,\n)\n```\n\n`DownloadResult` fields (available when using `create_completed_objects_thread`\nfor lower-level access):\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `key` | `str` | S3 object key |\n| `dest_filename` | `Path` | Absolute local destination path |\n| `success` | `bool` | `True` on success, `False` on failure |\n| `file_size` | `int` | Bytes written (0 on failure or dry-run) |\n| `error` | `Exception \\| None` | Exception that caused the failure, or `None` |\n\n### Custom Progress Tracker\n\nImplement `ProgressProtocol` to receive aggregate counts during listing and\ndownloading:\n\n```python\nfrom s3fetch import download, ProgressProtocol\n\nclass MyTracker:\n    \"\"\"Minimal tracker that satisfies ProgressProtocol.\"\"\"\n\n    def increment_found(self) -\u003e None:\n        print(\".\", end=\"\", flush=True)  # one dot per object listed\n\n    def increment_downloaded(self, bytes_count: int) -\u003e None:\n        print(f\" +{bytes_count // 1024}KB\", end=\"\", flush=True)\n\nsuccess_count, failures = download(\n    \"s3://my-bucket/data/\",\n    progress_tracker=MyTracker(),\n)\n```\n\n## Troubleshooting\n\n### Existing files are silently overwritten\n\nS3Fetch does not check whether a file already exists before downloading. If you run S3Fetch\ntwice against the same download directory, existing files will be silently overwritten with\nthe latest version from S3.\n\nIf you want to avoid overwriting files, use a fresh download directory or move previously\ndownloaded files before re-running.\n\n### MacOS hangs when downloading using high number of threads\n\nFrom my testing this is caused by Spotlight on MacOS trying to index a large number of files at once.\n\nYou can exclude the directory you're using to store your downloads via the Spotlight system preference control panel.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frxvt%2Fs3fetch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frxvt%2Fs3fetch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frxvt%2Fs3fetch/lists"}