{"id":37190918,"url":"https://github.com/polastre/gphotos","last_synced_at":"2026-01-14T22:03:59.019Z","repository":{"id":278953020,"uuid":"936916764","full_name":"polastre/gphotos","owner":"polastre","description":"Golang Google Photos package and cli utilizing the Picker API to copy media","archived":false,"fork":false,"pushed_at":"2025-03-02T21:49:50.000Z","size":17,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-02T22:27:53.283Z","etag":null,"topics":["aws-s3","golang","golang-package","google","googlephotos"],"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/polastre.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":"2025-02-21T23:21:54.000Z","updated_at":"2025-03-02T21:49:53.000Z","dependencies_parsed_at":"2025-02-22T19:28:00.518Z","dependency_job_id":"e44f71fd-22e4-447f-9d70-593cc95984f9","html_url":"https://github.com/polastre/gphotos","commit_stats":null,"previous_names":["polastre/gphotos"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/polastre/gphotos","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/polastre%2Fgphotos","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/polastre%2Fgphotos/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/polastre%2Fgphotos/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/polastre%2Fgphotos/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/polastre","download_url":"https://codeload.github.com/polastre/gphotos/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/polastre%2Fgphotos/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28436268,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T21:32:52.117Z","status":"ssl_error","status_checked_at":"2026-01-14T21:32:33.442Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6: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","golang","golang-package","google","googlephotos"],"created_at":"2026-01-14T22:03:58.449Z","updated_at":"2026-01-14T22:03:59.005Z","avatar_url":"https://github.com/polastre.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# gphotos\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/polastre/gphotos.svg)](https://pkg.go.dev/github.com/polastre/gphotos)\n\nGolang Google Photos package and cli utilizing the Picker API. Includes the\nability to copy media from Google Photos to S3.\n\n## Install\n\n```sh\ngo get github.com/polastre/gphotos\n```\n\nRequires go 1.24.0 or higher.\n\n## Why this package?\n\nThere's two reasons this exists:\n\n1. Google stopped producing a Google Photos golang package a long time ago,\n   and...\n2. Google [deprecated their Google Photos album/mediaItems\n   APIs](https://developers.google.com/photos/support/updates) in favor of a\n   [Picker\n   API](https://developers.google.com/photos/picker/guides/get-started-picker).\n   The Picker API is not well documented and it would be helpful to have a\n   library that actually works.\n\n## About the Picker API\n\nGoogle's move to the Picker API for Google Photos completely changes how apps\nintegrate with photos.\n\nApps now have two ways of interacting via the API:\n\n1. Media and albums created by the app itself can be accessed through the normal\n   Library API. If the app is something like a photo frame or media backup\n   utility, it is highly unlikely your app created the album AND the media\n   inside it. Even moving photos to an album created by your app doesn't allow\n   your app to see them because the photos themselves weren't uploaded by your\n   app.\n2. Apps can redirect users to a \"Media Picker\" at Google Photos by creating a\n   \"picker session\" for that user. After the user picks their media to share\n   with the app, the app has access to those media items via the Picker API\n   until the picker session expires. The session usually expires within 24\n   hours, which means the app only has access to the picked media for a short\n   time.\n\nBased on these observations, I've come to the conclusion that the only logical\nsolution is to copy off the media from Google Photos while the picker session is\nstill valid, for use after the picker session is complete. AWS S3 is a logical\nplace to store this data so that your apps can fetch the media when they need\nit.\n\nThis repo and package provides implementations to support this workflow. See the\n`auth` and `picker` utilities below.\n\n## Gettings started with the API\n\nThe `picker` utility in [cmd/picker](./cmd/picker/main.go) is a good place to\nstart to understand the flow.\n\nThe first thing needed is Google OAuth credentials. If you don't have them,\nthere's a utility in `auth` that fetches the credentials from the command line\nby providing a sign in link and the capturing the results in a local callback.\n\nWith Google Credentials in hand (largely out of scope of this package), create\ncredentials:\n\n```go\ncreds := gphotos.Credentials{\n    ClientID:     args.GoogleClientID,\n    ClientSecret: args.GoogleClientSecret,\n    RefreshToken: args.Token,\n}\n```\n\nThen create a new Picker session for that user with Google Photos:\n\n```go\nsesh, err := creds.NewPickerSession()\nif err != nil {\n    panic(err)\n}\nfmt.Printf(\"Visit this URL to pick photos for the app:\\n%s\\n\\n\", sesh.PickerURI)\n```\n\nIf you're building this into a webapp, you can redirect the user at this point\nto the `PickerURI`. Be sure to do this in a new tab because Google doesn't send\nthe user back to your application when they're done, instead they see a screen\nthat says \"Done\" and nothing else.\n\nFrom this point, poll the Google Photos Picker API for the session to see when\nit is complete. You can optionally add callbacks to abort the process or print\nstatus.\n\n```go\nphotos, err := sesh.Poll(context.Background())\nif err != nil {\n    panic(err)\n}\nfmt.Printf(\"%d total items, now uploading to S3\\n\", len(photos))\n```\n\nIf you'd like to upload the media to S3 when you're done, optionally use the\n`UploadToS3` func.\n\n```go\ns3options := gphotos.NewS3Options(bucketName)\nerr := creds.UploadToS3(photos, s3options)\n```\n\n## Utility: `auth`\n\nThe `auth` cli will perform a new OAuth authentication with the Google auth\nservice. This is useful to get a refresh token that can be used with the Google\nPhotos Picker for a specific user.\n\n```\n% GOOGLE_CLIENT_ID=your_id GOOGLE_CLIENT_SECRET=your_secret go run cmd/auth/main.go\nVisit the following URL to authorize the app:\nhttps://accounts.google.com/o/oauth2/auth...\n```\n\nYou can get your client ID and secret from the Google API Console. See the\n[Google Photos configuration\ndocumentation](https://developers.google.com/photos/overview/configure-your-app).\n\nThe `refresh_token` returned will be needed as the `--token` input for the\n`picker` utility.\n\n## Utility: `picker`\n\nThe `picker` cli allows you to pick some photos from Google Photos and then copy\nthem to a S3 bucket of your choice.\n\nRun the command to see all the options. Note that all of the options are\nrequired including Google config, AWS config, token, and bucket.\n\n```\n% go run cmd/picker/main.go\nUsage: main --client-id CLIENT-ID --client-secret CLIENT-SECRET --awsaccesskeyid AWSACCESSKEYID --awssecretaccesskey AWSSECRETACCESSKEY --region REGION --token TOKEN --bucket BUCKET\n\nOptions:\n  --client-id CLIENT-ID [env: GOOGLE_CLIENT_ID]\n  --client-secret CLIENT-SECRET [env: GOOGLE_CLIENT_SECRET]\n  --awsaccesskeyid AWSACCESSKEYID [env: AWS_ACCESS_KEY_ID]\n  --awssecretaccesskey AWSSECRETACCESSKEY [env: AWS_SECRET_ACCESS_KEY]\n  --region REGION [env: AWS_REGION]\n  --token TOKEN, -t TOKEN\n                         Google OAuth Refresh Token\n  --bucket BUCKET, -b BUCKET\n                         Destination S3 Bucket\n  --help, -h             display this help and exit\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpolastre%2Fgphotos","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpolastre%2Fgphotos","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpolastre%2Fgphotos/lists"}