Access Google Photo API with Python using google-api-python-client
Asked Answered
D

4

15

According to Google API Client Libraries page it is possible to access the Google Photos API using the python client library, but after installing it using pip install -t lib/ google-api-python-client I don't see anything related to Photos API.

How can I use the Google built client library instead of manually calling the REST APIs?

Direct answered 28/5, 2018 at 20:39 Comment(1)
Thank you for the implementation below. Note that your first link above is out of date and the Google API Client Libraries page has a reference to the photos v1 API description under the Go language but not under Python. The generic python interface should read that specification and be able to use it generically.Epochmaking
S
8

Thanks to Ido Ran's and brillb's examples, I finally got my problem solved too. Some of the documentation links given above are not valid any more. Trying to enhance above examples, I found the page Google Photos APIs most useful. It not only documents the API, but also allows you to test your requests interactively - I probably never had gotten it to work without that testing capability. After entering your request, you can see your coding example in cURL, HTTP or JAVASCRIPT - but nothing for Python.

Besides producing a list of my albums, I was also interested in

  • link to each album,
  • list of images (in albums or not),
  • link to each my media items and the URL to find them

In order to get the link to the albums, you can extend the above examples simply by retrieving item['productUrl']. However, many times the URL did not work for me in Firefox, IE nor Edge (error 404 after showing the album very briefly), but it did in Chrome and Opera (who knows why).

Much more reliable seems to be the URL of the album's cover photo: item['coverPhotoMediaItemId'] and there you'll find links to the album(s) under Info.

Instead of using the albums method, you can also access sharedAlbums (and specify results.get('sharedAlbums', []). I was hoping to be able to get the shareableUrl, but never found the ShareInfo resource as part of the results.

For the list of images, you have the choice of two methods: mediaItems.list and mediaItems.search. I don't consider the former useful since it returns a long list of all your images, while the search allows for limiting the results by the date, the picture was taken (not uploaded!). There is also a get and batchGet, I never tried because you need to know item ID given to the image by Google photos.

Each method has a limit (pageSize) for the maximum of entries to be returned. If there are more than that, it also sends a pageToken, you can use to request the next part.

I finally came up with this example:

from os.path import join, dirname
from googleapiclient.discovery import build
from httplib2 import Http
from oauth2client import file, client, tools
SCOPES = 'https://www.googleapis.com/auth/photoslibrary.readonly'

store = file.Storage(join(dirname(__file__), 'token-for-google.json'))
creds = store.get()
if not creds or creds.invalid:
    flow = client.flow_from_clientsecrets(join(dirname(__file__), 'client_id.json', SCOPES))
    creds = tools.run_flow(flow, store)
google_photos = build('photoslibrary', 'v1', http=creds.authorize(Http()))

day, month, year = ('0', '6', '2019')  # Day or month may be 0 => full month resp. year
date_filter = [{"day": day, "month": month, "year": year}]  # No leading zeroes for day an month!
nextpagetoken = 'Dummy'
while nextpagetoken != '':
    nextpagetoken = '' if nextpagetoken == 'Dummy' else nextpagetoken
    results = google_photos.mediaItems().search(
            body={"filters":  {"dateFilter": {"dates": [{"day": day, "month": month, "year": year}]}},
                  "pageSize": 10, "pageToken": nextpagetoken}).execute()
    # The default number of media items to return at a time is 25. The maximum pageSize is 100.
    items = results.get('mediaItems', [])
    nextpagetoken = results.get('nextPageToken', '')
    for item in items:
            print(f"{item['filename']} {item['mimeType']} '{item.get('description', '- -')}'"
                      f" {item['mediaMetadata']['creationTime']}\nURL: {item['productUrl']}")
Sloth answered 15/6, 2019 at 15:57 Comment(4)
Please read this to avoid wasting a lot of time. Google Photos API only let you control data you created from your App and not preexisting data. So if you want to move around preexisting pics, update their descriptions or add them to albums .. you cant. You can't touch preexisting data in any way. Read this -> https://mcmap.net/q/824244/-google-photo-returns-quot-error-400-request-contains-an-invalid-media-item-id-invalid_argument-quot-when-adding-a-media-item-into-an-existing-albumAdmiration
That saved a lot of time for sure!Chickasaw
I'm not sure what exactly @SanJay is referring to. But this is April 13, 2022, with the photoslibrary API I was able to list albums, or list photo contents. However, I needed to add static_discovery=False to the build method sourceEckardt
@Abu Sufian, it was always possible to list albums and photos, but San Jay's point is a different one: "if you want to move around preexisting pics, update their descriptions or add them to albums .. you cant." That is, you cannot use the API to change anything, for example the description of photos or albums, delete photos or albums, or move photos from one album to another.Sloth
D
7

I didn't find any example so I took the Drive API v3 example and adapted it to Photos v1 API.

You can see and use the example.

The gist is:

from apiclient.discovery import build

service = build('photoslibrary', 'v1', http=creds.authorize(Http()))
results = service.albums().list(
    pageSize=10, fields="nextPageToken,albums(id,title)").execute()
Direct answered 29/5, 2018 at 5:53 Comment(1)
Thanks! would love it, if someone could post examples on how to update the photos (patch/post rest calls) e.g. to update the description or date of a photoAdmiration
I
6

The API is a bit less capable than indicated in the example above, it doesn't support "fields". But it does work:

from googleapiclient.discovery import build
from httplib2 import Http
from oauth2client import file, client, tools
SCOPES = 'https://www.googleapis.com/auth/photoslibrary.readonly'

store = file.Storage('token-for-google.json')
creds = store.get()
if not creds or creds.invalid:
    flow = client.flow_from_clientsecrets('client_id.json', SCOPES)
    creds = tools.run_flow(flow, store)
gdriveservice = build('photoslibrary', 'v1', http=creds.authorize(Http()))

results = gdriveservice.albums().list(
    pageSize=10).execute()
items = results.get('albums', [])
for item in items:
        print(u'{0} ({1})'.format(item['title'].encode('utf8'), item['id']))
Inkberry answered 2/1, 2019 at 1:48 Comment(0)
L
-1

Check out the API's documentation here.

And more specifically here. Seems to be pretty limited though.

Lymphoblast answered 28/5, 2018 at 20:43 Comment(3)
I found both of them but after installing the library I don’t see the api to importDirect
Have you tried import googleapiclient.photoslibrary ?Lymphoblast
@ArdentLearner: That import gives me "ImportError: No module named photoslibrary".Interrogation

© 2022 - 2024 — McMap. All rights reserved.