We're making changes to the Community, so you may have received some notifications - thanks for your patience and welcome back. Learn more here.
Forum Discussion
David S.118
2 years agoHelpful | Level 5
How can a script or app get a shareable Dropbox link?
I'm trying to automate a task I've been doing for a while that's taking way too much time, and it requires me to send a sharable link to someone for some files in my Dropbox. So I have a script I've written but ... where I'd normally right-click to get a sharable link for a file, how can I get such a link within the script? I know the file locally on my machine, but how can I get a sharable Dropbox link? Can I use the Dropbox API for that? or is there a simpler way?
- ЗдравкоLegendary | Level 20
Hi David S.118,
You can take a look on thread' post here for an idea how that can be done. 😉
Hope this helps.
- David S.118Helpful | Level 5
Thanks. I'm not sure what language that example script is in.
I need this to run in Windows.
After looking through a bunch of related posts, it looks like there might be a command-line tool that I can run in Windows that does this.
- ЗдравкоLegendary | Level 20
David S.118 wrote:... I'm not sure what language that example script is in.
...
Hi again David S.118,
Hah..😯 You said "I have a script I've written but...", but seems you don't have too much experience, since can distinguish one of the most popular scripting languages - Python. Some parts of the official Dropbox application is implemented in the same language also. Even more, it's mentioned in the script header line. Didn't you read it? Anyway... it's my wrong assumption; I'll try to be more descriptive.
David S.118 wrote:...
I need this to run in Windows.
...
Oh... The script, I linked to, targets Mac and Linux only; on Windows can run but not in the same form. I just made some tweaks to let it work on Windows. Since it's Python script, you have to have Python interpreter installed, if you haven't yet, to be able run it. So first download and install the interpreter from here. Make sure you have selected all accessibility on install time:
Once the interpreter installed you may need some additional packages available, so make sure they are there. Execute following commands in terminal window:
py -m pip install --upgrade pip py -m pip install platformdirs py -m pip install dropbox
Now you have everything needed to run the script that let you get Dropbox links. The following is updated script version, working on Windows too:
#!/usr/bin/python3 ############################################################################### # Script receiving Dropbox links based on referred local files/folders # -------------------------------------------------------------------- # Every target file/folder is passed as argument to the script. Resulted links # are passed in the same sequence one per line to standard output (incorrect # are skipped). # Two preparation steps are needed: # 1. Register a Dropbox application and put the application key as value of # APPLICATION_KEY global variable. # 2. Register the used REDIRECT_URI in the application just created in # previous step. With host 'localhost' and port 8080, the redirect URL # that has to be registered is "http://localhost:8080/", for instance. # Next, just make it executable (if needed), using: # $ chmod a+x get_dropbox_link # ... and put it in a place visible for execution in your system (somewhere in # folders pointed by $PATH environment variable). On first run you will be # invited to link your script to your Dropbox account. To work correct local # Dropbox application and this script have to be link to the same account! # Verified on Dropbox v172.4.7555 # Author: Здравко # www.dropboxforum.com/t5/user/viewprofilepage/user-id/422790 ############################################################################### from dropbox import Dropbox, DropboxOAuth2Flow from dropbox.exceptions import ApiError from dropbox.oauth import NotApprovedException import json from pathlib import Path from datetime import datetime from os import sep, name, makedirs from sys import exit import logging from platformdirs import user_config_path # Place to save current configuration CONFIG_JSON=user_config_path('get_dropbox_link') / 'cred.json' # Take a look on your application in https://www.dropbox.com/developers/apps APPLICATION_KEY='PUT YOUR KEY HERE' URI_HOST='localhost' URI_PORT=8080 # URI should be registered in the application redirect URIs list!!! REDIRECT_URI=f"http://{URI_HOST}:{URI_PORT}/" success_response = "End of authentication flow. 😉 Your can get a link!" cancel_response = "🤷 You have denied your application's work. 😕" error_response = "😈 You got an error: " class ApplicationConfig: def __init__(self, conf_path=CONFIG_JSON): self.conf_path=Path(conf_path).expanduser() self.conf=None self.client=None self.access_token=None self.access_token_expiresat=None self.refresh_token=None makedirs(self.conf_path.parent, exist_ok=True) if self.conf_path.is_file(): try: with self.conf_path.open() as fconf: self.conf=json.load(fconf) self.access_token = self.conf['access_token'] self.access_token_expiresat = datetime.fromtimestamp( self.conf['access_token_expiresat']) self.refresh_token = self.conf['refresh_token'] except Exception: self.conf_path.unlink(True) self.conf=None def __del__(self): "Checks for something changed (new access token) and dumps it when there is" if (self.client is not None and self.client._oauth2_access_token_expiration > self.access_token_expiresat): self.conf['access_token'] = self.client._oauth2_access_token self.conf['access_token_expiresat'] = ( self.client._oauth2_access_token_expiration.timestamp()) self.conf['refresh_token'] = self.client._oauth2_refresh_token with self.conf_path.open(mode='w') as fconf: json.dump(self.conf, fconf) def getClient(self): "Gets Dropbox client object. Performs OAuth flow if needed." if self.conf is None: self.client=None import webbrowser from http.server import HTTPServer, BaseHTTPRequestHandler dbxAuth=DropboxOAuth2Flow(APPLICATION_KEY, REDIRECT_URI, {}, 'dropbox-auth-csrf-token', token_access_type='offline', use_pkce=True) webbrowser.open(dbxAuth.start()) conf=None conf_path = self.conf_path class Handler(BaseHTTPRequestHandler): response_success = success_response.encode() response_cancel = cancel_response.encode() response_error = error_response.encode() def do_GET(self): nonlocal dbxAuth, conf from urllib.parse import urlparse, parse_qs query = parse_qs(urlparse(self.path).query) for r in query.keys(): query[r] = query[r][0] self.send_response(200) self.send_header("content-type", "text/plain;charset=UTF-8") try: oauthRes = dbxAuth.finish(query) conf={'access_token': oauthRes.access_token, 'access_token_expiresat': oauthRes.expires_at.timestamp(), 'refresh_token': oauthRes.refresh_token} with conf_path.open(mode='w') as fconf: json.dump(conf, fconf) except NotApprovedException: conf={} self.send_header("content-length", f"{len(Handler.response_cancel)}") self.end_headers() self.wfile.write(Handler.response_cancel) self.wfile.flush() return except Exception as e: conf={} r = Handler.response_error + str(e).encode() self.send_header("content-length", f"{len(r)}") self.end_headers() self.wfile.write(r) self.wfile.flush() return self.send_header("content-length", f"{len(Handler.response_success)}") self.end_headers() self.wfile.write(Handler.response_success) self.wfile.flush() httpd=HTTPServer((URI_HOST, URI_PORT), Handler) while conf is None: httpd.handle_request() httpd.server_close() del httpd if 'refresh_token' not in conf: raise RuntimeError("Cannot process because missing authentication") self.conf = conf self.access_token = self.conf['access_token'] self.access_token_expiresat = datetime.fromtimestamp( self.conf['access_token_expiresat']) self.refresh_token = self.conf['refresh_token'] # Makes sure there is cached client object. if self.client is None: self.client=Dropbox(self.access_token, oauth2_refresh_token=self.refresh_token, oauth2_access_token_expiration=self.access_token_expiresat, app_key=APPLICATION_KEY) return self.client class PathMapper: def __init__(self): if name == 'nt': dbx_info = user_config_path() / 'Dropbox' / 'info.json' else: dbx_info = Path('~/.dropbox/info.json').expanduser() if not dbx_info.is_file(): raise RuntimeError("Missing Dropbox application information") with dbx_info.open() as finfo: # Only personal accounts are supported by now - group accounts need # additional namespace handling (just changing 'personal' is not enough). # Somebody else may make some exercises. self.dbx_path = json.load(finfo)['personal']['path'] def __contains__(self, path): path = str(Path(path).expanduser().absolute()) return ((len(path) == len(self.dbx_path) and path == self.dbx_path) or (len(path) > len(self.dbx_path) and path[len(self.dbx_path)] == sep and path[:len(self.dbx_path)] == self.dbx_path)) def __getitem__(self, path): path = str(Path(path).expanduser().absolute()) if ((len(path) == len(self.dbx_path) and path == self.dbx_path) or (len(path) > len(self.dbx_path) and path[len(self.dbx_path)] == sep and path[:len(self.dbx_path)] == self.dbx_path)): return Path(path[len(self.dbx_path):]).as_posix() def main(): import argparse dbxPathMap = PathMapper() parser = argparse.ArgumentParser(description="Fetch Dropbox URL for path") parser.add_argument("paths", type=str, nargs="+", help="paths to files") parser.add_argument("--verbose", "-v", action="store_true", help="toggle verbose mode") args = parser.parse_args() del parser if args.verbose: logging.basicConfig(level=logging.DEBUG) conf = ApplicationConfig() dbx = conf.getClient() for path in args.paths: if path not in dbxPathMap: logging.error(f"Passed path '{path}' is not part of the Dropbox driectory tree") continue dbx_path = dbxPathMap[path] if len(dbx_path) == 0: logging.error("Dropbox folder itself cannot be pointed by link") continue logging.debug(f"Processing local file '{path}' with Dropbox path '{dbx_path}'") try: metadata = dbx.sharing_create_shared_link_with_settings(dbx_path) except ApiError as e: er = e.error if not er.is_shared_link_already_exists(): raise er = er.get_shared_link_already_exists() if not er.is_metadata(): raise metadata = er.get_metadata() print(metadata.url) if __name__ == "__main__": try: main() except Exception as e: logging.error(f"Unexpected error: {e}") exit(1)
Save above script in a file named "get_dropbox_link" on place convenient for you. Since this script uses Dropbox API, you need to register your application here. Select "Full Dropbox" as access type, since you will need access to files in entire account, not only application specific files. Make sure "sharing.write" is selected scope in your application permission (to be able create and get shared links). In section Redirect URIs, ensure URL "http://localhost:8080/" is present (add it as needed). On the same page is field named App key; copy the value/key shown there to corresponding place in the script (near beginning - it's the only redaction you have to make). Now you're almost ready. Type in the terminal something like:
py <exec path to>\get_dropbox_link <path into Dropbox>
Here <exec path to> is optional path to the place you put the script on. You may need to use such explicit path when the script is not directly visible from the place you're calling from. <path into Dropbox> is path to file/folder, residing within your local Dropbox folder, you want to get shared link to. That's it. 😉 You can ether extend this script and/or call it from any other script (doesn't have to be Python script; can be any other script).
Good luck.
About Create, upload, and share
Find help to solve issues with creating, uploading, and sharing files and folders in Dropbox. Get support and advice from the Dropbox Community.
Need more support
If you need more help you can view your support options (expected response time for an email or ticket is 24 hours), or contact us on X or Facebook.
For more info on available support options for your Dropbox plan, see this article.
If you found the answer to your question in this Community thread, please 'like' the post to say thanks and to let us know it was useful!