Skip to content

Instantly share code, notes, and snippets.

@prasathmani
Last active September 26, 2026 06:56
Show Gist options
  • Select an option

  • Save prasathmani/5d78a6126c3e1920ffb6fd591a759edb to your computer and use it in GitHub Desktop.

Select an option

Save prasathmani/5d78a6126c3e1920ffb6fd591a759edb to your computer and use it in GitHub Desktop.
upload files to google drive using python
import json
import os
import requests
# ============================================================
# Google Drive configuration
# ============================================================
CLIENT_ID = "YOUR_CLIENT_ID"
CLIENT_SECRET = "YOUR_CLIENT_SECRET"
REFRESH_TOKEN = "YOUR_REFRESH_TOKEN"
# Google Drive folder ID
FOLDER_ID = "YOUR_GOOGLE_DRIVE_FOLDER_ID"
# Backup file to upload
UPLOAD_FILE = "/path/to/your/backup.zip"
# ============================================================
# Google OAuth / Drive URLs
# ============================================================
TOKEN_URL = "https://oauth2.googleapis.com/token"
UPLOAD_URL = (
"https://www.googleapis.com/upload/drive/v3/files"
"?uploadType=multipart"
)
# ============================================================
# Get a new access token using the refresh token
# ============================================================
def get_access_token():
data = {
"client_id": CLIENT_ID,
"client_secret": CLIENT_SECRET,
"refresh_token": REFRESH_TOKEN,
"grant_type": "refresh_token",
}
response = requests.post(TOKEN_URL, data=data)
if response.status_code != 200:
raise Exception(
f"Failed to get access token: {response.text}"
)
token_data = response.json()
access_token = token_data.get("access_token")
if not access_token:
raise Exception(
f"No access token returned: {token_data}"
)
return access_token
# ============================================================
# Upload file to Google Drive
# ============================================================
def upload_to_drive(access_token, file_path, folder_id):
if not os.path.isfile(file_path):
raise FileNotFoundError(
f"Backup file does not exist: {file_path}"
)
file_name = os.path.basename(file_path)
metadata = {
"name": file_name,
"parents": [folder_id],
}
headers = {
"Authorization": f"Bearer {access_token}",
}
# Keep the file open while requests.post() is running.
# This fixes the "read of closed file" error from the original Gist.
with open(file_path, "rb") as backup_file:
files = {
"data": (
"metadata",
json.dumps(metadata),
"application/json; charset=UTF-8",
),
"file": (
file_name,
backup_file,
"application/zip",
),
}
response = requests.post(
UPLOAD_URL,
headers=headers,
files=files,
timeout=3600,
)
if response.status_code not in (200, 201):
raise Exception(
f"Google Drive upload failed "
f"(HTTP {response.status_code}):\n"
f"{response.text}"
)
result = response.json()
print("Upload successful!")
print(f"File name: {result.get('name')}")
print(f"Google Drive file ID: {result.get('id')}")
# ============================================================
# Main
# ============================================================
def main():
print("Starting Google Drive backup upload...")
try:
print("Getting Google access token...")
access_token = get_access_token()
print(f"Uploading: {UPLOAD_FILE}")
upload_to_drive(
access_token,
UPLOAD_FILE,
FOLDER_ID,
)
print("Backup upload completed successfully.")
except Exception as e:
print(f"Error: {e}")
raise
# ============================================================
# Run
# ============================================================
if __name__ == "__main__":
main()
@ab9801

ab9801 commented Mar 23, 2023

Copy link
Copy Markdown

Awesome, was very useful for me

@prasathmani

Copy link
Copy Markdown
Author

Google Drive API Setup for Server Backup Script

This guide explains how to create Google Drive API credentials and generate a refresh token for a server-side backup script.

The final setup allows a server to upload a backup to a specific Google Drive folder without requiring you to log in every day.

Overview

The Python script requires these values:

CLIENT_ID
CLIENT_SECRET
REFRESH_TOKEN
FOLDER_ID
UPLOAD_FILE

The first three are obtained through Google OAuth 2.0.

The FOLDER_ID is obtained from the Google Drive folder URL.


1. Create a Google Cloud Project

Open:

https://console.cloud.google.com/

Create a new project.

For example:

Project name: Server Backup

Select the newly created project.


2. Enable Google Drive API

In Google Cloud Console:

Google Cloud Console
    ↓
APIs & Services
    ↓
Library

Search for:

Google Drive API

Open it and click:

Enable

The Drive API must be enabled before the script can access Google Drive.


3. Configure Google Auth Platform

In the Google Cloud Console, go to:

Google Auth Platform

If Google asks you to configure the platform, click:

Get Started

Configure the application.

Example:

App name:
Server Backup

User support email:
your-email@gmail.com

Developer/contact email:
your-email@gmail.com

The current Google Cloud interface separates OAuth configuration into areas such as Branding, Audience, and Data Access.


4. Configure the Audience

Go to:

Google Auth Platform
    ↓
Audience

For a personal Google account, you can use:

External

if Internal is not available.

If you select External, your application can remain in Testing for your own use.

Add your Google account as a test user:

Test users
    ↓
Add users

Enter the Google account that owns the Drive folder:

your-email@gmail.com

Click:

Save

IMPORTANT:

If your account is not listed as a test user, Google may show:

Error 403: access_denied

with a message saying the app can only be accessed by developer-approved testers.


5. Configure the Drive OAuth Scope

Go to:

Google Auth Platform
    ↓
Data Access
    ↓
Add or Remove Scopes

For the backup script, use:

https://www.googleapis.com/auth/drive

This gives the application access to Google Drive.

Click:

Update

and then save the configuration.


6. Create an OAuth Client

Because we are using Google's OAuth 2.0 Playground to generate the refresh token, create a:

Web application

OAuth client.

Go to:

Google Auth Platform
    ↓
Clients
    ↓
Create Client

Select:

Application type:
Web application

Give it a name:

Server Backup OAuth

7. Add the OAuth Playground Redirect URI

Under:

Authorized redirect URIs

add exactly:

https://developers.google.com/oauthplayground

Do not add a trailing slash.

It must be:

https://developers.google.com/oauthplayground

and not:

https://developers.google.com/oauthplayground/

Click:

Create

Google will provide:

Client ID
Client Secret

Keep both values secure.

IMPORTANT:

The Client ID and Client Secret must be used together with the refresh token generated from the same OAuth client.


8. Open Google OAuth 2.0 Playground

Open:

https://developers.google.com/oauthplayground/

Google's OAuth Playground allows you to authorize your Google account and exchange the authorization code for an access token and refresh token.


9. Configure OAuth Playground

Click the gear/settings icon in the upper-right corner.

Enable:

Use your own OAuth credentials

Enter the Client ID and Client Secret created in the previous step.

Example:

OAuth Client ID:

123456789012-xxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com


OAuth Client Secret:

GOCSPX-xxxxxxxxxxxxxxxxxxxx

Use the exact values from your Google Cloud OAuth client.


10. Configure OAuth Flow

In OAuth Playground settings, use:

OAuth flow:
Server-side

Access type:
Offline

Force prompt:
Consent Screen

The important setting is:

Access type: Offline

Offline access is required to obtain a refresh token.


11. Select Google Drive Scope

In OAuth Playground, under:

Step 1 - Select & authorize APIs

Use the field:

Input your own scopes

Enter:

https://www.googleapis.com/auth/drive

Then click:

Authorize APIs

12. Sign in to Google

Google will open the authorization screen.

Sign in using the same Google account that you added as a test user.

For example:

your-email@gmail.com

Review the requested permissions and click:

Allow

If Google displays a warning that the application has not been verified, make sure you are using the account that was added as a test user.


13. Exchange Authorization Code for Tokens

After authorization, OAuth Playground will return to the Playground.

Go to:

Step 2 - Exchange authorization code for tokens

Click:

Exchange authorization code for tokens

OAuth Playground should return something similar to:

Refresh token:

1//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Access token:

ya29.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

The value you need for the server backup script is:

Refresh token

You do NOT need to manually put the access token into the Python script.

The Python script uses the refresh token to obtain a new access token whenever it runs.


14. Create the Google Drive Backup Folder

Open Google Drive:

https://drive.google.com/

Create a folder, for example:

Server Backups

Open the folder.

The browser URL will look similar to:

https://drive.google.com/drive/folders/1AbCdEfGhIjKlMnOpQrStUvWxYz

The folder ID is:

1AbCdEfGhIjKlMnOpQrStUvWxYz

Therefore:

FOLDER_ID=1AbCdEfGhIjKlMnOpQrStUvWxYz

15. Create credentials.env

Put credentials.env in the same directory as gdrive.py.

Example:

CLIENT_ID=123456789012-xxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com
CLIENT_SECRET=GOCSPX-xxxxxxxxxxxxxxxxxxxx
REFRESH_TOKEN=1//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
FOLDER_ID=1AbCdEfGhIjKlMnOpQrStUvWxYz
UPLOAD_FILE=/backup/database-backup.zip

Do not put quotes around the values.


16. Install Python Dependencies

Install requests:

python3 -m pip install requests

Install python-dotenv:

python3 -m pip install python-dotenv

Or:

pip install requests python-dotenv

17. Python Script Configuration

The Python script should load the credentials from credentials.env.

Example:

import json
import os
import requests

from dotenv import load_dotenv


BASE_DIR = os.path.dirname(os.path.abspath(__file__))
ENV_FILE = os.path.join(BASE_DIR, "credentials.env")

load_dotenv(ENV_FILE)


CLIENT_ID = os.getenv("CLIENT_ID")
CLIENT_SECRET = os.getenv("CLIENT_SECRET")
REFRESH_TOKEN = os.getenv("REFRESH_TOKEN")
FOLDER_ID = os.getenv("FOLDER_ID")
UPLOAD_FILE = os.getenv("UPLOAD_FILE")

Using the script directory is recommended because cron may execute the script from a different working directory.


18. Protect credentials.env

On Linux:

chmod 600 credentials.env

This prevents other normal users from reading the file.

If this directory is a Git repository, add this to .gitignore:

credentials.env

Never commit your refresh token or client secret to GitHub.


19. Verify the Configuration

Run:

python3 gdrive.py

A successful run should produce output similar to:

Starting Google Drive backup upload...
Getting Google access token...
Uploading: /backup/database-backup.zip
Upload successful!
File name: database-backup.zip
Google Drive file ID: xxxxxxxxxxxxxxxxx
Backup upload completed successfully.

20. Common Errors

Error: redirect_uri_mismatch

Example:

Error 400: redirect_uri_mismatch

Check the OAuth client in Google Cloud.

The Authorized redirect URI must be exactly:

https://developers.google.com/oauthplayground

Also make sure you are using a Web application OAuth client for OAuth Playground.


Error: access_denied

Example:

Error 403: access_denied

If the OAuth application is External and in Testing mode, add your Google account under:

Google Auth Platform
    ↓
Audience
    ↓
Test users

Then authorize again.


Error: unauthorized_client

Example:

Error: Failed to get access token:
{
  "error": "unauthorized_client"
}

Usually check that:

CLIENT_ID
CLIENT_SECRET
REFRESH_TOKEN

all belong to the same OAuth client.

Do not generate the refresh token using Client A and then use Client B's Client ID/Secret in the Python script.


Error: read of closed file

Example:

Error: read of closed file

This is caused by closing the backup file before the HTTP upload has finished.

Make sure the upload code keeps the file open while requests.post() or requests.patch() is running.

Use:

with open(file_path, "rb") as backup_file:
    response = requests.post(...)

instead of opening the file inside a with block and returning the closed file object.


21. How OAuth Works

The process is:

                 ONE-TIME SETUP

Google Cloud
     │
     ├── Client ID
     └── Client Secret
             │
             ▼
      OAuth Playground
             │
             ▼
       Google Login
             │
             ▼
       Authorization
             │
             ▼
       Refresh Token

The refresh token is then stored securely on your server.

Every day:

Cron
  │
  ▼
gdrive.py
  │
  ├── CLIENT_ID
  ├── CLIENT_SECRET
  └── REFRESH_TOKEN
          │
          ▼
   Google OAuth server
          │
          ▼
    New access token
          │
          ▼
     Google Drive API
          │
          ▼
      Upload backup

You do not need to manually obtain a new access token every day.

The refresh token is used to obtain fresh access tokens automatically.


22. Important Security Warning

Treat these values as secrets:

CLIENT_SECRET
REFRESH_TOKEN

Do NOT publish them in a GitHub Gist.

Your documentation can contain placeholders:

CLIENT_ID=YOUR_CLIENT_ID
CLIENT_SECRET=YOUR_CLIENT_SECRET
REFRESH_TOKEN=YOUR_REFRESH_TOKEN
FOLDER_ID=YOUR_FOLDER_ID
UPLOAD_FILE=/path/to/backup.zip

But never publish the real values.

If a real refresh token or client secret is accidentally published, revoke/rotate the credential immediately.


23. Recommended GitHub Repository Structure

A good structure is:

google-drive-backup/
│
├── gdrive.py
├── credentials.env.example
├── .gitignore
└── README.md

Create:

credentials.env.example

with:

CLIENT_ID=YOUR_CLIENT_ID
CLIENT_SECRET=YOUR_CLIENT_SECRET
REFRESH_TOKEN=YOUR_REFRESH_TOKEN
FOLDER_ID=YOUR_GOOGLE_DRIVE_FOLDER_ID
UPLOAD_FILE=/path/to/backup.zip

Then .gitignore:

credentials.env
__pycache__/
*.pyc

The real credentials.env stays only on your server.


Official Google References

Google OAuth 2.0 Playground:

https://developers.google.com/oauthplayground/

Google Drive API Python quickstart:

https://developers.google.com/workspace/drive/api/quickstart/python

Google OAuth consent configuration:

https://developers.google.com/workspace/guides/configure-oauth-consent

Google OAuth Playground documentation:

https://developers.google.com/search-ads/reporting/concepts/oauth-playground


Disclaimer

This guide was generated with the assistance of AI. It is provided for informational purposes only. Google Cloud Console, OAuth, and Google Drive API interfaces and requirements may change over time. Always verify the current Google documentation before configuring authentication or using this setup in production.

Do not share or publish your Google OAuth Client Secret, Refresh Token, or other credentials.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment