---
name: download-google-drive-file
description: Download files from Google Drive that require confirmation due to virus scan warnings or size limits.
---
# Download Google Drive File with Confirmation Handling

## Description
Downloads files from Google Drive that may require confirmation due to virus scan warnings or size limits. Handles the HTML interstitial page that appears for large files.

## When to Use
- When you need to download a file from Google Drive via a direct link
- When the file is large enough to trigger Google Drive's virus scan warning
- When standard download methods fail due to confirmation requirements

## Prerequisites
- None (works with standard Python libraries)

## Steps
1. **Parse input and construct initial download URL**\n   - Accept either a raw file ID or a full Google Drive share link\n   - Extract file ID from share links using patterns like:\n     * `drive.google.com/file/d/[FILE_ID]/view`\n     * `drive.google.com/open?id=[FILE_ID]`\n   - Construct initial export URL: `https://drive.google.com/uc?export=download&id=[FILE_ID]`\n\n2. **Make initial request**\n   - Send GET request to the export URL\n   - Check if response is HTML (indicating virus scan warning or login requirement)\n\n3. **Handle virus scan warning (if present)**\n   - Parse HTML to find form with id=\"download-form\" or any form\n   - Extract form action URL\n   - Extract all hidden input fields (especially confirm token)\n   - Build final download URL with all parameters\n   - ALTERNATIVE: If wget/curl available, use cookie handling approach:\n     * `wget --load-cookies /tmp/cookies.txt \"https://docs.google.com/uc?export=download&confirm=$(wget --quiet --save-cookies /tmp/cookies.txt --keep-session-cookies --no-check-certificate 'https://docs.google.com/uc?export=download&id=[FILE_ID]' -O- | sed -rn 's/.*confirm=([0-9A-Za-z_]+).*/\\1\\np')&id=[FILE_ID]\" -O [OUTPUT]`\n\n4. **Download the file**\n   - Send GET request to final download URL (or use wget/curl with cookies)\n   - Save response content to file\n\n5. **Process downloaded file**\n   - Check if file is a zip archive\n   - If zip, extract contents\n   - For Node/pnpm projects: inspect structure without mandatory installation\n   - Return file information and extraction status\n\n## Parameters\n- `file_id_or_url`: The Google Drive file ID OR full share link\n- `output_path`: Optional path to save the downloaded file (default: current directory)\n- `extract`: Whether to extract if file is a zip archive (default: true)\n- `source_only`: For Node projects, create archive excluding node_modules and build artifacts (default: false)\n\n## Example Usage (Python)\n```python\nimport os\nimport urllib.request\nimport urllib.parse\nimport re\nimport zipfile\n\ndef download_google_drive_file(file_id_or_url, output_path=\".\", extract=True, source_only=False):\n    # Extract file ID from various Google Drive URL formats\n    file_id = file_id_or_url\n    if 'drive.google.com' in file_id_or_url:\n        # Pattern: https://drive.google.com/file/d/FILE_ID/view\n        match = re.search(r'/file/d/([^/]+)/', file_id_or_url)\n        if match:\n            file_id = match.group(1)\n        else:\n            # Pattern: https://drive.google.com/open?id=FILE_ID\n            match = re.search(r'[?&]id=([^&]+)', file_id_or_url)\n            if match:\n                file_id = match.group(1)\n    \n    # Step 1: Initial URL\n    # NOTE: base_url already includes export=download; do NOT add it to params (would duplicate and cause 400)\n    base_url = \"https://drive.google.com/uc?export=download\"\n    params = {\"id\": file_id}\n    url = f\"{base_url}?{urllib.parse.urlencode(params)}\"\n    # Alternative working URL format: f\"https://docs.google.com/uc?export=download&id={file_id}\"\n    \n    # Step 2: Initial request\n    req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5.0'})\n    resp = urllib.request.urlopen(req)\n    html = resp.read().decode('utf-8', errors='ignore')\n    \n    # Step 3: Check for virus scan warning\n    if '<html' in html.lower():\n        # Parse form\n        action_match = re.search(r'<form[^>]*action=\"([^\"]+)\"', html, re.IGNORECASE)\n        action = action_match.group(1) if action_match else \"https://drive.usercontent.google.com/download\"\n        \n        # Extract inputs\n        inputs = re.findall(r'<input[^>]*>', html, re.IGNORECASE)\n        params = {}\n        for inp in inputs:\n            name_match = re.search(r'name=\"([^\"]+)\"', inp, re.IGNORECASE)\n            value_match = re.search(r'value=\"([^\"]*)\"', inp, re.IGNORECASE)\n            if name_match:\n                name = name_match.group(1)\n                value = value_match.group(1) if value_match else ''\n                params[name] = value\n        \n        # Build final URL\n        query = urllib.parse.urlencode(params)\n        final_url = f\"{action}?{query}\"\n    else:\n        # Direct download (no warning)\n        final_url = url\n    \n    # Step 4: Download file\n    req = urllib.request.Request(final_url, headers={'User-Agent': 'Mozilla/5.0'})\n    resp = urllib.request.urlopen(req)\n    data = resp.read()\n    \n    # Determine filename\n    filename = f\"drive_download_{file_id}\"\n    if not output_path.endswith('/'):\n        output_path += '/'\n    filepath = os.path.join(output_path, filename)\n    \n    with open(filepath, 'wb') as f:\n        f.write(data)\n    \n    # Step 5: Process file\n    result = {\n        \"filepath\": filepath,\n        \"size_bytes\": len(data),\n        \"extracted\": False\n    }\n    \n    if extract and zipfile.is_zipfile(filepath):\n        with zipfile.ZipFile(filepath, 'r') as zf:\n            zf.extractall(output_path)\n        result[\"extracted\"] = True\n        result[\"extracted_files\"] = zf.namelist()\n        \n        # Optional: create source-only archive for Node projects\n        if source_only:\n            import tarfile\n            source_archive = filepath.replace('.zip', '_source.tar.gz')\n            with tarfile.open(source_archive, 'w:gz') as tar:\n                for member in zf.namelist():\n                    # Skip node_modules, build artifacts, etc.\n                    if not any(excluded in member for excluded in [\n                        'node_modules/', '.git/', 'dist/', 'build/', '.next/', 'coverage/\n                    ]):\n                        tar.add(os.path.join(output_path, member), arcname=member)\n            result[\"source_archive\"] = source_archive\n    \n    return result\n```\n\n## Pitfalls\n- Google Drive may change their HTML structure; selectors may need updating\n- Some files may require additional parameters or different handling\n- Large files may take significant time to download\n- The confirm token is typically a single character like \"t\"\n- Files that require authentication will return an HTML login page instead of the file\n- After extraction, setting up a Node/pnpm project may encounter version mismatches or permission issues in restricted environments\n- In restricted environments, standard tools like wget, curl, gdown may not be available; the skill relies on built-in Python libraries\n\n## Post-extraction steps for Node/pnpm projects\nIf the downloaded file is a zip containing a Node.js/pnpm project (look for package.json, pnpm-lock.yaml), consider the following steps:\n\n1. **Check package.json** for scripts, dependencies, and any version constraints (e.g., \"engines\": {\"node\": \">=xx\"}).\n2. **Try installing dependencies**:\n   - If pnpm is available and matches the required version, run `pnpm install`.\n   - If pnpm is not available or version mismatched, try using npm or yarn (if present in lockfile).\n   - In restricted environments (no sudo, older Node), you may encounter permission errors or version warnings.\n3. **Handle Node version mismatches**:\n   - If the project requires a newer Node version than available, consider using nvm to install the required version (if permitted) or inspecting the source code directly without running.\n   - If you cannot change Node version, many projects can still be inspected for code review, configuration, etc.\n4. **If installation fails due to permissions or version**, fall back to inspecting the source code:\n   - Read source files (`.ts`, `.js`, `.json`) to understand the project structure and logic.\n   - Look for configuration files (like `.env.example`, `replit.md`) to learn about required environment variables.\n5. **Set environment variables** as needed:\n   - Check for `.env.example` or documentation (e.g., `replit.md`) for required variables.\n   - Create a `.env` file with the necessary values (e.g., API tokens, database URLs) and ensure it is not committed to version control.\n6. **Run scripts** (if installation succeeded):\n   - Use `pnpm run <script>` or `npm run <script>` to execute build, test, or dev commands as defined in package.json.\n\n## Verification (post-extraction)\n- Confirm that the extracted contents match the expected project structure.\n- If you attempted installation, check for a `node_modules` directory or lockfile changes.\n- If you inspected the code, verify that you could read key files (e.g., API routes, bot logic) without errors.\n\n## Verification\n- Check that the downloaded file size matches expected size\n- For zip files, verify extraction completed successfully\n- Look for expected files in extracted contents\n\n## Related Skills\n- None currently