-
-
Save prasathmani/5d78a6126c3e1920ffb6fd591a759edb to your computer and use it in GitHub Desktop.
| 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() |
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:
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.zipDo not put quotes around the values.
16. Install Python Dependencies
Install requests:
python3 -m pip install requestsInstall python-dotenv:
python3 -m pip install python-dotenvOr:
pip install requests python-dotenv17. 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.envThis 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.pyA 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.zipBut 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.zipThen .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.
Awesome, was very useful for me