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.
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?
Hi @David S.118,
You can take a look on thread' post here for an idea how that can be done. 😉
Hope this helps.
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.
@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.
Hi there!
If you need more help you can view your support options (expected response time for a 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!