This is a package to fetch data from Upwork API
Project description
Upwork Fetcher CLI
A powerful Python command-line tool that fetches and stores Upwork job postings using the Upwork GraphQL API. This tool helps freelancers and agencies efficiently search, filter, and track job opportunities from Upwork.
Features
- Job Fetching: Search for jobs using multiple search expressions with Lucene syntax support
- Database Storage: Automatically stores job data in PostgreSQL database with deduplication
- Database Configuration: Store all credentials and configuration in the database for centralized management
- Rich CLI Interface: Beautiful command-line interface with tables and progress indicators
- OAuth2 Authentication: Secure authentication with Upwork API using OAuth2 flow with automatic token refresh
- Flexible Filtering: Support for various search criteria and pagination
- Data Persistence: Prevents duplicate job entries and maintains historical data
- Multi-Instance Support: Multiple instances can share the same configuration via database
Prerequisites
- Python 3.12 or higher
- PostgreSQL database
- Upwork API credentials (Client ID, Client Secret, Redirect URI)
Installation
Using Poetry (Recommended)
# Clone the repository
git clone <repository-url>
cd upwork-automation-cli
# Install dependencies
poetry install
# Activate virtual environment
poetry shell
Using pip
pip install upwork-fetcher
Configuration
1. Upwork API Setup
- Go to Upwork Developers
- Create a new application
- Note down your Client ID, Client Secret, and set up a Redirect URI
2. Database Setup
Set up a PostgreSQL database and note the connection URL:
postgresql://username:password@host:port/database_name
Usage
Initial Setup
Configure your Upwork API credentials:
# Setup with database storage (recommended)
upwork-fetcher setup \
--client_id "your_client_id" \
--client_secret "your_client_secret" \
--redirect_uri "your_redirect_uri" \
--db-url "postgresql://user:pass@host:port/dbname"
# Or use environment variable
export UPWORK_DB_URL="postgresql://user:pass@host:port/dbname"
upwork-fetcher setup --client_id "your_client_id" --client_secret "your_client_secret" --redirect_uri "your_redirect_uri"
This will:
- Save your API credentials to the database (or local file as fallback)
- Open an authorization URL in your browser
- Prompt you to enter the authorization code
- Exchange the code for access and refresh tokens
- Store all configuration in the
upwork_configstable
Fetching Jobs
Search and fetch jobs with various options:
# Basic job search
upwork-fetcher fetch -s "python" --limit 20
# Multiple search expressions
upwork-fetcher fetch -s "react" -s "node.js" -s "typescript" --limit 50
# With database URL (if not configured)
upwork-fetcher fetch -s "machine learning" --db-url "postgresql://user:pass@localhost:5432/upwork_jobs"
# Verbose output with job details table
upwork-fetcher fetch -s "django" --verbose --limit 10
# With pagination
upwork-fetcher fetch -s "flutter" --offset 20 --limit 30
Command Options
setup command
--client_id: Your Upwork API client ID--client_secret: Your Upwork API client secret--redirect_uri: Your configured redirect URI--db-url: Database URL for storing credentials (optional)
fetch command
-s, --search-expression: Search expression (can be used multiple times)--limit: Maximum number of jobs to fetch (default: 50)--offset: Number of jobs to skip (default: 0)--db-url: PostgreSQL database URL-v, --verbose: Show detailed job information in table format
Project Structure
upwork_fetcher/
├── cli.py # Main CLI entry point
├── commands.py # CLI command implementations
├── config.py # Configuration management (supports database and file storage)
├── schema.py # Pydantic schemas for data validation
├── models/
│ ├── jobs.py # Database model for jobs
│ ├── upwork_config.py # Database model for configuration
│ └── dbcontext/
│ └── dbcontext.py # Database context manager
├── services/
│ └── upwork_service.py # Main service for Upwork API interaction
└── queries/
└── market_place_job.py # GraphQL queries
Database Schema
The tool creates two main tables:
job table
- Basic Info:
id,title,description,category - Budget:
amount_raw_value,amount_currency,hourly_budget_min/max - Requirements:
skills,experience_level,duration - Client Info:
client_total_hires,client_total_spent,client_location_* - Timestamps:
created_date_time,published_date_time
upwork_configs table
- Credentials:
client_id,client_secret,redirect_uri - Tokens:
access_token,refresh_token,token_type,expires_in - Settings:
db_url,code - Timestamps:
created_at,updated_at
Configuration Storage
Database Storage (Recommended)
When a database URL is provided, all configuration is stored in the upwork_configs table. This allows:
- Multiple instances to share the same configuration
- Centralized credential management
- Automatic token persistence after refresh
- No local files needed
File Storage (Fallback)
If no database URL is provided, configuration is stored in ~/.upwork_fetcher/config.json:
{
"client_id": "your_client_id",
"client_secret": "your_client_secret",
"redirect_uri": "your_redirect_uri",
"access_token": "...",
"refresh_token": "...",
"code": "...",
"db_url": "postgresql://..."
}
Environment Variables
You can also use environment variables:
export UPWORK_DB_URL="postgresql://user:pass@host:port/dbname"
Search Expressions
The tool supports Upwork's search syntax including:
- Keywords:
"python developer" - Skills:
"react AND typescript" - Boolean operators:
"(python OR django) AND NOT wordpress" - Phrases:
"machine learning engineer"
Error Handling
- Authentication: Automatically refreshes access tokens when expired (both tokens are updated)
- Database: Validates database URL format and connectivity
- API Errors: Graceful handling of API rate limits and errors
- Duplicates: Prevents storing duplicate job entries
- Token Persistence: Automatically saves new tokens after refresh to prevent loss
Development
Setting up for Development
# Clone repository
git clone <repository-url>
cd upwork-automation-cli
# Install dependencies with dev tools
poetry install --with dev
# Run tests
poetry run pytest
# Format code
poetry run black .
# Type checking
poetry run mypy .
Building and Publishing
# Update version
poetry version [patch | minor | major]
# Build package
poetry build
# Publish to PyPI
poetry publish
Deployment Instructions
# Update version
poetry version [patch | minor | major]
# Create git tag
git tag $(poetry version -s)
# Commit and push
git add .
git commit -m "Release $(poetry version -s)"
git push origin main --tags
Dependencies
- click: Command-line interface framework
- requests: HTTP client for API calls
- gql: GraphQL client
- psycopg2-binary: PostgreSQL adapter
- tortoise-orm: Async ORM for database operations
- pydantic: Data validation and settings
- rich: Rich text and beautiful formatting
- python-dotenv: Environment variable loading
Troubleshooting
Common Issues
-
Authentication Errors
- Verify your API credentials
- Check if access token has expired (tool auto-refreshes)
- Ensure redirect URI matches your Upwork app configuration
- Note: Both access and refresh tokens change on every refresh
-
Database Connection Issues
- Verify PostgreSQL is running
- Check database URL format (supports both
postgres://andpostgresql://) - Ensure database exists and user has proper permissions
- The
upwork_configstable is created automatically
-
No Jobs Found
- Try different search expressions
- Check if search terms are too specific
- Verify Upwork API is accessible
-
Configuration Not Persisting
- Ensure database URL is set correctly
- Check write permissions on database
- Verify the
upwork_configstable exists
Logging
Enable verbose mode to see detailed information:
upwork-fetcher fetch -s "python" --verbose
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
License
This project is licensed under the MIT License.
Disclaimer
This tool is for educational and legitimate job search purposes only. Please respect Upwork's Terms of Service and API usage guidelines. The authors are not responsible for any misuse of this tool.
Support
For issues and questions:
- Check the troubleshooting section
- Review existing GitHub issues
- Create a new issue with detailed information
Running in Scripts
You can run the fetch command programmatically:
#!/usr/bin/env python3
import sys
from upwork_fetcher.cli import cli
if __name__ == "__main__":
sys.argv = [
"upwork-fetcher",
"fetch",
"-s", "python developer",
"-s", "django developer",
"--limit", "50"
]
cli()
Or use subprocess:
import subprocess
result = subprocess.run([
"upwork-fetcher", "fetch",
"-s", "python developer",
"--limit", "50"
], capture_output=True, text=True)
Version History
- 0.1.16: Database configuration storage, improved token handling
- 0.1.15: Enhanced error handling and type hinting
- 0.1.14: Improved job schema conversion with error handling
- Previous versions: Various bug fixes and feature enhancements
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file upwork_fetcher-0.1.17.tar.gz.
File metadata
- Download URL: upwork_fetcher-0.1.17.tar.gz
- Upload date:
- Size: 15.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
42ebe768d033d146a253630ac7638fb73385f29f79c4c565f803e56fa154e13a
|
|
| MD5 |
05b43d9d8d18ad69fd1212d5f3047ba6
|
|
| BLAKE2b-256 |
ba9dfaf9ff1d792063db8a3ac790eb9e29e17c4879f80990c1304dfe26571452
|
Provenance
The following attestation bundles were made for upwork_fetcher-0.1.17.tar.gz:
Publisher:
release.yaml on iSemantics-ai/upwork-fetcher
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
upwork_fetcher-0.1.17.tar.gz -
Subject digest:
42ebe768d033d146a253630ac7638fb73385f29f79c4c565f803e56fa154e13a - Sigstore transparency entry: 293062992
- Sigstore integration time:
-
Permalink:
iSemantics-ai/upwork-fetcher@6b8b0d7a75b9126dd100cc3a79552cca34a99ba5 -
Branch / Tag:
refs/tags/0.1.17 - Owner: https://github.com/iSemantics-ai
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@6b8b0d7a75b9126dd100cc3a79552cca34a99ba5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file upwork_fetcher-0.1.17-py3-none-any.whl.
File metadata
- Download URL: upwork_fetcher-0.1.17-py3-none-any.whl
- Upload date:
- Size: 15.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
56b938c58c2a200bfeed6d60e72a3b3bd9553f6c42bca0788516df0eaeca53b2
|
|
| MD5 |
6d0fc8dd53e22f67ccf04c9fa4a79d6b
|
|
| BLAKE2b-256 |
34235ad444012df8e4803014ae98a1073bf89239bd5b71c3b3be880440449168
|
Provenance
The following attestation bundles were made for upwork_fetcher-0.1.17-py3-none-any.whl:
Publisher:
release.yaml on iSemantics-ai/upwork-fetcher
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
upwork_fetcher-0.1.17-py3-none-any.whl -
Subject digest:
56b938c58c2a200bfeed6d60e72a3b3bd9553f6c42bca0788516df0eaeca53b2 - Sigstore transparency entry: 293063023
- Sigstore integration time:
-
Permalink:
iSemantics-ai/upwork-fetcher@6b8b0d7a75b9126dd100cc3a79552cca34a99ba5 -
Branch / Tag:
refs/tags/0.1.17 - Owner: https://github.com/iSemantics-ai
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@6b8b0d7a75b9126dd100cc3a79552cca34a99ba5 -
Trigger Event:
push
-
Statement type: