Skip to main content

Overview

Skyvern provides comprehensive file handling capabilities including uploading files to web forms, downloading files from websites, and parsing document content (PDFs, spreadsheets, etc.) for use in workflows.

File Upload

Basic File Upload

Upload files to web forms using natural language:
from skyvern import Skyvern

skyvern = Skyvern(api_key="your-api-key")

browser = await skyvern.launch_cloud_browser()
page = await browser.get_working_page()

await page.goto("https://example.com/upload")

# Upload using natural language prompt
await page.upload_file(
    prompt="Upload resume file",
    files="/path/to/resume.pdf"
)

# Or use traditional selector with AI fallback
await page.upload_file(
    "#file-input",
    prompt="Upload document",
    files="/path/to/document.docx"
)

Multiple File Upload

# Upload multiple files at once
await page.upload_file(
    prompt="Attach supporting documents",
    files=[
        "/path/to/resume.pdf",
        "/path/to/cover_letter.pdf",
        "/path/to/references.pdf"
    ]
)

Upload in Workflows

Use the upload action in task prompts:
task = await skyvern.run_task(
    prompt="Go to the job application form and upload the resume file located at resume.pdf",
    url="https://careers.example.com/apply",
    # Files are automatically handled by Skyvern
)

File Upload Action Type

Skyvern automatically detects file upload fields:
from skyvern.webeye.actions.actions import UploadFileAction

# Skyvern creates UploadFileAction when it detects file inputs
action = UploadFileAction(
    file_url="s3://bucket/path/to/file.pdf",  # S3 URI
    # OR
    file_name="document.pdf",  # Local file name
    is_upload_file_tag=True,  # Detected as file input
)

File Download

Downloading Files

Skyvern automatically captures file downloads:
task = await skyvern.run_task(
    prompt="Download the latest invoice PDF",
    url="https://example.com/invoices"
)

# Access downloaded files
for file in task.downloaded_files:
    print(f"Downloaded: {file.file_name}")
    print(f"URL: {file.presigned_url}")  # Presigned URL to download
    print(f"Size: {file.file_size} bytes")

Download Configuration

Skyvern automatically configures download behavior:
# Downloads are saved to: /app/downloads/{org_id}/{browser_session_id}/
# Files are automatically uploaded to block storage if configured

Workflow Download Actions

from skyvern.webeye.actions.actions import DownloadFileAction

# Skyvern creates DownloadFileAction for download links
action = DownloadFileAction(
    file_url="https://example.com/files/document.pdf",
    download=True,  # Trigger download
    download_triggered=True,  # Download was initiated
    downloaded_files=["invoice_2024.pdf"],  # Files downloaded
)

Download Monitoring

Skyvern waits for downloads to complete:
# Automatic download timeout: 30 seconds default
# Max wait time for download completion: 60 seconds

# Downloads are monitored via Chrome DevTools Protocol (CDP)
await page.click(prompt="Download report")
# Skyvern automatically waits for download to complete

File Parsing

Parse document content and use it in workflows:

PDF Parsing

# In a workflow, use FileParserBlock
from skyvern.forge.sdk.workflow.models.block import BlockType

# Workflow YAML example:
workflow = {
    "blocks": [
        {
            "block_type": "file_url_parser",
            "label": "parse_invoice",
            "file_url": "s3://bucket/invoices/latest.pdf",
            "file_type": "pdf"
        },
        {
            "block_type": "task",
            "label": "extract_data",
            "prompt": "Extract invoice number and total from: {{ parse_invoice.output }}"
        }
    ]
}

Supported File Types

  • PDF: Extract text content from PDF documents
  • Spreadsheets: Parse CSV, Excel files
  • Images: OCR and image analysis
  • Documents: Word docs, text files

File Parser Block

Use in workflow definitions:
blocks:
  - block_type: file_url_parser
    label: parse_document
    file_url: "{{ previous_block.downloaded_files[0].s3_uri }}"
    file_type: pdf
    
  - block_type: extraction
    label: extract_invoice_data
    data_extraction_goal: |
      Extract the following from the parsed document:
      - Invoice number
      - Invoice date
      - Total amount
      - Vendor name
    data_schema:
      type: object
      properties:
        invoice_number:
          type: string
        invoice_date:
          type: string
        total_amount:
          type: number
        vendor_name:
          type: string
    context: "{{ parse_document.output }}"

File Storage

Uploading Files to Storage

Upload files to S3/block storage:
# Via API
response = await skyvern.upload_file(
    file_path="/path/to/document.pdf",
    file_name="document.pdf"
)

print(f"S3 URI: {response.s3_uri}")
print(f"Download URL: {response.presigned_url}")

API Endpoint

curl -X POST https://api.skyvern.com/api/v1/files/upload \
  -H "x-api-key: your-api-key" \
  -F "file=@/path/to/document.pdf" \
  -F "file_name=document.pdf"
Response:
{
  "s3_uri": "s3://skyvern-uploads/org_123/document.pdf",
  "presigned_url": "https://s3.amazonaws.com/..."
}

File Information Schema

from skyvern.forge.sdk.schemas.files import FileInfo

class FileInfo(BaseModel):
    file_name: str              # Original file name
    file_size: int              # Size in bytes
    s3_uri: str                 # S3 storage location
    presigned_url: str          # Temporary download URL
    content_type: str | None    # MIME type

Advanced Use Cases

1. Invoice Processing Workflow

workflow_run = await skyvern.run_workflow(
    workflow_id="wpid_invoice_processor",
    parameters={
        "vendor_portal_url": "https://vendor.example.com"
    }
)

# Workflow steps:
# 1. Login to vendor portal
# 2. Navigate to invoices
# 3. Download all invoices from last month
# 4. Parse each PDF
# 5. Extract invoice data
# 6. Upload to accounting system

for file in workflow_run.downloaded_files:
    print(f"Processed: {file.file_name}")

2. Bulk Document Upload

import asyncio
from pathlib import Path

async def upload_documents(directory: str):
    """Upload all PDFs from a directory"""
    files = list(Path(directory).glob("*.pdf"))
    
    # Upload to storage first
    uploaded_files = []
    for file_path in files:
        response = await skyvern.upload_file(
            file_path=str(file_path),
            file_name=file_path.name
        )
        uploaded_files.append(response.s3_uri)
    
    # Use in workflow
    await skyvern.run_workflow(
        workflow_id="wpid_document_processor",
        parameters={
            "document_uris": uploaded_files
        }
    )

3. Download and Parse Pattern

blocks:
  # Step 1: Download file
  - block_type: task
    label: download_report
    url: https://example.com/reports
    navigation_goal: Download the latest quarterly report
    
  # Step 2: Parse downloaded file
  - block_type: file_url_parser
    label: parse_report
    file_url: "{{ download_report.downloaded_files[0].s3_uri }}"
    file_type: pdf
    
  # Step 3: Extract data from parsed content
  - block_type: extraction
    label: extract_metrics
    data_extraction_goal: Extract quarterly revenue and profit
    context: "{{ parse_report.output }}"
    data_schema:
      type: object
      properties:
        revenue:
          type: number
        profit:
          type: number
        quarter:
          type: string

4. Form Auto-Fill from Document

# Parse source document
response = await skyvern.upload_file(
    file_path="employee_data.csv",
    file_name="employee_data.csv"
)

# Use parsed data in form filling
task = await skyvern.run_task(
    prompt=f"""
    Fill out the employee registration form using data from the CSV.
    For each row in the CSV, create a new employee entry.
    """,
    url="https://hr.example.com/register",
    data_extraction_schema={
        "employees_processed": "number",
        "errors": "array"
    }
)

Best Practices

File Upload Best Practices

  1. Use Descriptive Prompts
# Good
await page.upload_file(
    prompt="Upload company logo in the profile section",
    files="logo.png"
)

# Less specific
await page.upload_file(
    prompt="Upload file",
    files="logo.png"
)
  1. Validate File Size
from pathlib import Path

file_path = Path("/path/to/large_file.pdf")
if file_path.stat().st_size > 10 * 1024 * 1024:  # 10MB
    print("File too large, consider splitting")
  1. Handle Upload Errors
try:
    await page.upload_file(
        prompt="Upload document",
        files="document.pdf"
    )
except Exception as e:
    print(f"Upload failed: {e}")
    # Retry or handle error

File Download Best Practices

  1. Always Check Downloaded Files
task = await skyvern.run_task(
    prompt="Download invoice",
    url="https://example.com/invoices"
)

if not task.downloaded_files:
    print("No files were downloaded")
    # Handle missing download
else:
    for file in task.downloaded_files:
        if file.file_size == 0:
            print(f"Warning: {file.file_name} is empty")
  1. Use Presigned URLs Quickly
# Presigned URLs expire after a certain time
for file in task.downloaded_files:
    # Download immediately or save URL for short-term use
    async with httpx.AsyncClient() as client:
        response = await client.get(file.presigned_url)
        with open(f"local_{file.file_name}", "wb") as f:
            f.write(response.content)

File Parsing Best Practices

  1. Validate Parsed Content
- block_type: file_url_parser
  label: parse_doc
  file_url: "{{ file_uri }}"
  
- block_type: validation
  label: check_content
  validation_goal: Verify the parsed document contains expected sections
  1. Handle Large Documents
# For large documents, consider pagination or chunking
# Parse in smaller sections if needed

Troubleshooting

File Upload Issues

File not uploading:
# Ensure file path is absolute
import os
absolute_path = os.path.abspath("relative/path/to/file.pdf")

await page.upload_file(
    prompt="Upload file",
    files=absolute_path
)
Wrong upload field:
# Be more specific in prompt
await page.upload_file(
    prompt="Upload file to the main document field, not the thumbnail field",
    files="document.pdf"
)

Download Issues

Downloads not captured:
  • Ensure download links are clicked, not just navigation
  • Check if site uses JavaScript for downloads
  • Verify download completed within timeout period
# Increase timeout for large files
# Configure via environment or task settings

Parsing Issues

Parsed content is empty:
  • Verify file is not encrypted or password-protected
  • Check file format is supported
  • Ensure file was fully downloaded before parsing

Build docs developers (and LLMs) love