Get Dropbox folder path in Python

Question:

I need to know the local Dropbox path in any machine (mac or windows) whereever is this file (might be in a seconcary hard drive) and whatever is its name (might be ‘E:My_funny_dropbox’). I’m using the dropbox API. In the Dropbox website, I’ve set a token to grant access to "files.metadata.read". The token was saved in an environment variable for security reasons, where I can successlully read it.
Here is the current code:

Attempting to use the Dropbox API to locate the Dropbox directory. 

import os, dropbox

"""Acquiring necessary variables"""
tokens = os.environ
access_token = tokens['DROPBOX_ACCESS_TOKEN'] 
if __name__ == "__main__":
    print(f"The Dropbox access token is: {access_token}")  # The access token to my Dropbox as previously saved in the system. So far so good. thiw works.

# Initialize the Dropbox API with your access token
dbx = dropbox.Dropbox(access_token)

# Get the Dropbox user's account information
account_info = dbx.users_get_current_account()

# Get the root folder information
# The program stucks here
root_folder = dbx.files_get_metadata("/")

# Get the path to the root folder
dropbox_path = root_folder.path_display

In case it helps the full log is:

E:DropboxpythonProject1Scriptspython.exe "E:DropboxpythonProject1dropbox_folder.py" 
The Dropbox access token is: *** got the right token ***
Traceback (most recent call last):
  File "E:DropboxpythonProject1Libsite-packagesrequestsmodels.py", line 971, in json
    return complexjson.loads(self.text, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:UsersmeAppDataLocalProgramsPythonPython311Libjson__init__.py", line 346, in loads
    return _default_decoder.decode(s)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:UsersmeAppDataLocalProgramsPythonPython311Libjsondecoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:UsersmeAppDataLocalProgramsPythonPython311Libjsondecoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "E:DropboxpythonProject1Libsite-packagesdropboxdropbox_client.py", line 624, in raise_dropbox_error_for_resp
    if res.json()['error'] == 'invalid_grant':
       ^^^^^^^^^^
  File "E:DropboxpythonProject1Libsite-packagesrequestsmodels.py", line 975, in json
    raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)
requests.exceptions.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "E:DropboxpythonProject1dropbox_folder.py", line 20, in <module>
    root_folder = dbx.files_get_metadata("/")
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "E:DropboxpythonProject1Libsite-packagesdropboxbase.py", line 1671, in files_get_metadata
    r = self.request(
        ^^^^^^^^^^^^^
  File "E:DropboxpythonProject1Libsite-packagesdropboxdropbox_client.py", line 326, in request
    res = self.request_json_string_with_retry(host,
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "E:DropboxpythonProject1Libsite-packagesdropboxdropbox_client.py", line 476, in request_json_string_with_retry
    return self.request_json_string(host,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "E:DropboxpythonProject1Libsite-packagesdropboxdropbox_client.py", line 596, in request_json_string
    self.raise_dropbox_error_for_resp(r)
  File "E:DropboxpythonProject1Libsite-packagesdropboxdropbox_client.py", line 632, in raise_dropbox_error_for_resp
    raise BadInputError(request_id, res.text)
dropbox.exceptions.BadInputError: BadInputError('db812a8d6e8948308f2439a3ca50bc53', 'Error in call to API function "files/get_metadata": request body: path: The root folder is unsupported.')

Process finished with exit code 1

To my best undesrtanding the meaning of this lies in the last line: ‘path: The root folder is unsupported’. which seems related to this line of the program: root_folder = dbx.files_get_metadata("/"). Dropbox API is said to accept an empy string instead, like this: root_folder = dbx.files_get_metadata("") but it doesn’t.

Asked By: quickbug

||

Answers:

Per the Dropbox API documentation:

https://www.dropbox.com/developers/documentation/http/documentation#files-get_metadata

Returns the metadata for a file or folder. Note: Metadata for the root folder is unsupported.

I don’t think the server API supports a way to get the local path for your desktop client; for a given user account on the server side you might have multiple linked clients, or no linked clients. The server API allows you to work with the files in Dropbox independently of any local client app.

If you want to figure out where you might have local files that are synced by the Dropbox client, what I might suggest is scanning the local hard drive for .dropbox files (starting with the default ~/Dropbox paths, but you can in theory have a Dropbox folder anywhere). You should be able to correlate the data in that file with the info you get from the server’s get_current_user endpoint.

Answered By: Samwise

If I understand your question properly, you’re trying to find the local Dropbox path. The API does not know this, it can only tell you about the files in your Dropbox.

This article describes how to find the local Dropbox path. In Python, this can be done as follows:

import os.path
import json

INFO_PATHS = ["%APPDATA%Dropboxinfo.json",
              "%LOCALAPPDATA%Dropboxinfo.json"]

def find_dbx_path(path):
    """ Try and open info.json to retreive Dropbox path """
    try:
        with open(os.path.expandvars(path), "r") as f:
            data = json.load(f)
            return list(data.values())[0]["path"]
    except: pass

""" Look for file """
for path in INFO_PATHS:
    dbx_path = find_dbx_path(path)
    # if path found stop searching
    if dbx_path:
        break

print(dbx_path)

There are two paths on a Windows machine (INFO_PATHS) where the info.json file is. The JSON is of the form

{'personal': {'path': 'pathtodropbox', 'host': 01234567890, 'is_team': False, 'subscription_type': 'Basic'}}

The key may be 'personal' or 'business' so I’ve just used .values() on the dictionary so it’ll work regardless.

Answered By: Henry
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.