Unofficial Python client for the GoPro cloud API (api.gopro.com): sync and async clients, Pydantic models, and a CLI.
Project description
gopro-api
Unofficial Python client for the GoPro cloud / Quik HTTP API at api.gopro.com: search your library and fetch download metadata (CDN URLs, filenames, variants). Built with Pydantic models, plus sync (requests) and async (aiohttp) clients and a small gopro-api CLI.
This project is not affiliated with or endorsed by GoPro.
Features
GoProAPI— synchronous client (requests),withcontext managerAsyncGoProAPI— async client (aiohttp),async withcontext manager- Pydantic request/response types in
gopro_api.api.models - CLI —
gopro-api search,gopro-api info,gopro-api pull GP_ACCESS_TOKENfrom environment /.env(browser cookie value)
Requirements
- Python 3.10+
GP_ACCESS_TOKEN— see Configuration
Install
From the repository root:
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
pip install -e .
From a local wheel (name matches your build):
pip install ./dist/gopro_api-*-py3-none-any.whl
Published package on PyPI (distribution name gopro-api, import gopro_api):
pip install gopro-api
CLI
After install, gopro-api is on your PATH:
gopro-api --help
gopro-api --version
gopro-api search --start 2026-03-01 --end 2026-03-03 --per-page 30
gopro-api search --start 2026-03-01 --end 2026-03-03 --all-pages
gopro-api search --start 2026-03-01 --end 2026-03-03 --json
gopro-api info MEDIA_ID
gopro-api info MEDIA_ID --json
gopro-api pull MEDIA_ID ./downloads
gopro-api pull MEDIA_ID ./downloads --height 1080
gopro-api pull MEDIA_ID ./downloads --width 1920 --height 1080
| Command | Purpose |
|---|---|
search |
List media in a capture range. Default: a # _pages summary line, a tab-separated header (id, type, captured_at, filename, …; not gopro_user_id / source_gumi / source_mgumi), then one row per item (other API fields in an extra JSON column). --json: full API-shaped response; with --all-pages, a JSON array of every page. |
info |
Show download metadata for one media id (filename + file lines with size and URL), or --json for the full payload. |
pull |
Download asset(s) for a media id into destination (directory; created if missing). Videos (.mp4 extension, case-insensitive): one variations entry — tallest by default, or closest to --height / --width (sum of squared pixel deltas; ties broken by larger resolution). Photos: uses files (one request per file). |
Global --timeout (seconds, default 60) applies to API calls and to pull CDN downloads (requests.get).
Run without an installed script:
python -m gopro_api.cli search --start 2026-03-01 --end 2026-03-02
python -m gopro_api.cli info MEDIA_ID
python -m gopro_api.cli pull MEDIA_ID ./out
python -m gopro_api.cli pull MEDIA_ID ./out --height 720
Configuration
gopro_api.config reads settings from the environment and from a .env file in the current working directory via pydantic-settings. The only required setting is GP_ACCESS_TOKEN.
Example .env:
GP_ACCESS_TOKEN=your_token_here
The clients send it as a cookie: gp_access_token=<value>. Put only the token string in GP_ACCESS_TOKEN (not the gp_access_token= prefix).
You can override the token in code: GoProAPI(access_token="...") or AsyncGoProAPI(access_token="...").
Retrieving gp_access_token from your browser
Sign in to the GoPro web app (e.g. gopro.com media / Quik). The site sets a cookie gp_access_token.
Chrome / Edge / Brave
- Open the site while logged in.
- F12 → Application → Cookies → choose the origin (often
https://quik.gopro.comor another*.gopro.comhost). - Copy the Value of
gp_access_token.
Firefox
F12 → Storage → Cookies → same idea.
Network panel (Chromium)
- Network → trigger requests to
api.gopro.com. - Pick a request → Headers → Cookie.
- Copy the value after
gp_access_token=up to the next;(or end of string).
Notes
- If the cookie is HttpOnly, use the Network method.
- Tokens expire; refresh from the browser if you get 401.
- Treat the token like a password.
Security: Do not commit .env or tokens. Keep .env in .gitignore.
Library usage
Async (AsyncGoProAPI)
import asyncio
from datetime import datetime
from gopro_api.api import AsyncGoProAPI
from gopro_api.api.models import CapturedRange, GoProMediaSearchParams
async def main() -> None:
params = GoProMediaSearchParams(
captured_range=CapturedRange(
start=datetime.fromisoformat("2026-03-01"),
end=datetime.fromisoformat("2026-03-02"),
),
per_page=50,
page=1,
)
async with AsyncGoProAPI() as api:
search = await api.search(params)
for item in search.embedded.media:
meta = await api.download(item.id)
print(meta.filename, len(meta.embedded.files), "files")
if __name__ == "__main__":
asyncio.run(main())
Sync (GoProAPI)
from datetime import datetime
from gopro_api.api import GoProAPI
from gopro_api.api.models import CapturedRange, GoProMediaSearchParams
def main() -> None:
params = GoProMediaSearchParams(
captured_range=CapturedRange(
start=datetime.fromisoformat("2026-03-01"),
end=datetime.fromisoformat("2026-03-02"),
),
per_page=50,
page=1,
)
with GoProAPI() as api:
search = api.search(params)
for item in search.embedded.media:
meta = api.download(item.id)
print(meta.filename, len(meta.embedded.files), "files")
if __name__ == "__main__":
main()
Models
- Requests:
GoProMediaSearchParams,CapturedRange, etc. ingopro_api.api.models. - Responses: search and download JSON shapes (including
_embedded/_pagesaliases).
List fields in search params are serialized to comma-separated strings when you call model_dump() (used by the HTTP clients).
Project layout
| Path | Role |
|---|---|
gopro_api/api/gopro.py |
GoProAPI — sync search, download |
gopro_api/api/async_gopro.py |
AsyncGoProAPI — async search, download |
gopro_api/api/models.py |
Pydantic request/response models |
gopro_api/api/__init__.py |
Re-exports GoProAPI, AsyncGoProAPI |
gopro_api/config.py |
pydantic-settings Settings, GP_ACCESS_TOKEN |
gopro_api/cli.py |
gopro-api CLI |
setup.py |
Package metadata, dependencies, console entry point |
CI and releases
.github/workflows/release.yml:
- Push to
main— builds wheel + source.zip, uploads workflow artifacts. - Push tag
v*(e.g.v0.0.5) — attaches the same files to a GitHub Release.
License
GoPro, Quik, and related marks are trademarks of their respective owners.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gopro_api-0.0.8.tar.gz.
File metadata
- Download URL: gopro_api-0.0.8.tar.gz
- Upload date:
- Size: 129.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c07a92b0357a720deb2f4292e28c804bf5ca05b154e64be63c1b706874fb1665
|
|
| MD5 |
da211966e0d8c9d27673ff12b07838b6
|
|
| BLAKE2b-256 |
27e7f4202cd000bf4739f7cc447f771ef28478be0fc399cf10400c6676b2d2ec
|
File details
Details for the file gopro_api-0.0.8-py3-none-any.whl.
File metadata
- Download URL: gopro_api-0.0.8-py3-none-any.whl
- Upload date:
- Size: 22.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b93aa6c793cf0784da621ed1841e5776f7217e1acbd324ceba8447a059675dc2
|
|
| MD5 |
3670e4a6a74687db0e993cca28e2c8db
|
|
| BLAKE2b-256 |
ffd84cad5803ee0a0850a096f7c9cbe2f004c5fa2677c47a165b7d97973e64a4
|