Download materials from Virtuale (Moodle) courses using secure cookie handling
Project description
Virtuale Course Materials Downloader
This script downloads downloadable files from a course on Virtuale (Moodle) using your authenticated browser session cookie.
What It Does
- Connects to a Virtuale course page
- Scans course resource/folder pages for downloadable files
- Downloads all discovered files to a target folder
- Overwrites existing files when the filename is the same
Requirements
- Python 3.10+
requestspackagekeyringpackage (optional, strongly recommended for secure credential storage)
Install dependencies:
python -m pip install requests keyring
Install For Other Users
Option A: install directly from GitHub (fastest)
Recommended for end users that just want the command:
pipx install "git+https://github.com/g-mainardi/scraping-virtuale.git"
Or with plain pip:
python -m pip install "git+https://github.com/g-mainardi/scraping-virtuale.git"
Then verify:
virtuale-dl --help
Option B: install from PyPI (after you publish)
pipx install virtuale-dl
# or
python -m pip install virtuale-dl
Publish The Package (Maintainer)
Option A: GitHub Actions (recommended)
This repository includes an automated workflow at:
.github/workflows/release.yml
Behavior:
- Push tag
v*(example:v0.1.0) -> build + publish to PyPI - Manual run (
workflow_dispatch) -> build + publish to TestPyPI
Required one-time setup:
- Create package projects on TestPyPI and PyPI (
virtuale-dl) - In each index, configure Trusted Publisher with owner
g-mainardi, repositoryscraping-virtuale, and workflowrelease.yml - If you add environment restrictions in the publisher settings, create matching GitHub environments first
Release commands:
# Test release (manual from GitHub UI):
# Actions -> Release Python Package -> Run workflow
# Production release:
git tag v0.1.0
git push origin v0.1.0
Option B: manual twine upload
One-time setup:
python -m pip install --upgrade build twine
python -m twine check --help
For each release:
# 1) bump version in pyproject.toml
# 2) build
python -m build
# 3) validate artifacts
python -m twine check dist/*
# 4) publish to TestPyPI first (recommended)
python -m twine upload --repository testpypi dist/*
# 5) publish to PyPI
python -m twine upload dist/*
After publishing, users can install with pipx install virtuale-dl.
Security: Credential Storage
IMPORTANT: Never pass cookies on the command line to production systems or AI agents. This script uses a secure fallback chain:
- System Keyring (Windows Credential Manager) - most secure, recommended ✅
VIRTUALE_MOODLE_SESSIONenvironment variable--moodle-sessionCLI argument (for special cases only)- Interactive prompt with
getpass(no echo to terminal)
Recommended Setup: Keyring (One-time)
Store your cookie securely using Python's keyring package:
# Get fresh cookie from browser (see "How to Get MoodleSession" below)
# Then store it securely:
python -m keyring set virtuale-moodle moodle YOUR_COOKIE_VALUE
This stores your cookie in Windows Credential Manager (encrypted, OS-managed).
After one-time setup, you can run:
python scraping_virtuale.py IRS
# No credential needed! Script retrieves it from keyring automatically.
This is ideal for AI Agents - they can invoke the tool without handling any secrets!
Easier: Use the Helper Script
Instead of manually copying the cookie and running the keyring command, use the included helper:
./refresh-virtuale-cookie.cmd
This script will:
- Guide you to DevTools & the Cookies tab
- Ask for the cookie (hidden from terminal for security)
- Store it securely in Windows Credential Manager
- Clear sensitive data from memory
First-time setup:
./refresh-virtuale-cookie.cmd
# Follow the interactive prompts -> done!
When cookie expires (next day or after logout):
./refresh-virtuale-cookie.cmd
# Get fresh cookie -> done!
If automatic authentication fails (for example: No MoodleSession found in keyring/env or The cookie is invalid or expired), run ./refresh-virtuale-cookie.cmd again and then retry virtuale-dl.
Then use the downloader normally:
virtuale-dl IRS
Alternative setup using environment variable (less secure)
# Set environment variable (consider adding to PowerShell profile for persistence):
$env:VIRTUALE_MOODLE_SESSION = "YOUR_COOKIE_VALUE"
python scraping_virtuale.py IRS
Script Files
scraping_virtuale.py- main downloadercourse_ids.json- course code -> Moodle course ID mappingrefresh-virtuale-cookie.ps1- local helper that stores MoodleSession in keyringrefresh-virtuale-cookie.cmd- Windows launcher for the local PowerShell helpersync-refresh-cookie-global.ps1- copies local refresh scripts to your global bin folder
Keep Global Script In Sync
If you edit the local repo scripts and also want your globally installed command updated, run:
powershell -NoProfile -ExecutionPolicy Bypass -File .\sync-refresh-cookie-global.ps1
Default source files:
./refresh-virtuale-cookie.ps1./refresh-virtuale-cookie.cmd
Default global target folder:
%USERPROFILE%\\bin
Example with custom destination:
powershell -NoProfile -ExecutionPolicy Bypass -File .\sync-refresh-cookie-global.ps1 -InstallDir "C:\\tools\\bin"
CLI Usage
virtuale-dl SELECTED_COURSE [OUTPUT_DIR] [--moodle-session COOKIE] [--course-ids-file PATH] [--max-pages N] [--debug-scan]
Positional Arguments
SELECTED_COURSE(required): one of:IRS,ASMD,PM,SAP,SPE,DS,old-ASMD,old-PM
OUTPUT_DIR(optional): destination folder for downloaded files
If OUTPUT_DIR is omitted, the script uses automatic defaults:
- Standard courses:
<BASE_DIR>/<SELECTED_COURSE>/materials - Historical:
old-ASMD-><BASE_DIR>/ASMD/old_materials,old-PM-><BASE_DIR>/PM/old_materials
<BASE_DIR> is resolved as:
VIRTUALE_OUTPUT_BASE_DIRenvironment variable (if set)- Otherwise, your user home directory
Missing folders are created automatically.
Options
--moodle-session(optional): MoodleSession cookie value. If omitted, script tries keyring → env var → prompt.--course-ids-file(optional): path to JSON file with course IDs (default: built-in course IDs, orcourse_ids.jsonif present next to script)--max-pages(optional, default:300): max number of resource/folder pages to crawl--debug-scan(optional): print crawler progress details
Course IDs Configuration
The script reads course mappings from course_ids.json.
Example format:
{
"IRS": "72659",
"ASMD": "71106",
"old-ASMD": "59758"
}
Provide a different mapping with --course-ids-file PATH.
How to Get MoodleSession Cookie
- Log in to Virtuale in your browser
- Open browser DevTools (F12)
- Go to Storage/Application → Cookies →
https://virtuale.unibo.it - Find
MoodleSessioncookie - Copy its value (long alphanumeric string)
- Store it:
python -m keyring set virtuale-moodle moodle <VALUE>
Cookie expires after browser session/inactivity. If you get auth errors, repeat the above steps to get a fresh one.
Usage Examples
After keyring setup (recommended):
# Most basic - retrieves cookie from keyring automatically
virtuale-dl IRS
With optional custom output:
virtuale-dl PM ~/Downloads/PM_Materials
With debug output:
virtuale-dl SAP --max-pages 120 --debug-scan
With environment variable (if keyring not available):
$env:VIRTUALE_MOODLE_SESSION = "cookie_value"
python scraping_virtuale.py IRS
With CLI argument (not recommended, only for special cases):
python scraping_virtuale.py IRS --moodle-session "cookie_value"
Typical Output
On success:
Authenticated for course ...Found N downloadable file link(s).Downloaded: ...Download completed. Saved N file(s) in: ...
On invalid/expired cookie:
Error: The cookie is invalid or expired. You need a fresh one.- Fix: run
./refresh-virtuale-cookie.cmdand then runvirtuale-dl IRSagain.
Notes
- The script only follows Virtuale links
- It discovers files through resource and folder pages
- Non-download HTML pages are skipped during download
- If a file with the same name already exists, it is replaced.
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 virtuale_dl-0.1.0.tar.gz.
File metadata
- Download URL: virtuale_dl-0.1.0.tar.gz
- Upload date:
- Size: 12.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0b496a0af5053a6601280bd1256b96b67d35b184c99b16a6e7bbe024f9421b55
|
|
| MD5 |
2a47a7658518c9c305d6d505c7867055
|
|
| BLAKE2b-256 |
5da37ea281628d13bfa87a3c321e898acbe92517c724d84bf4a38c8c6bab758a
|
Provenance
The following attestation bundles were made for virtuale_dl-0.1.0.tar.gz:
Publisher:
release.yml on g-mainardi/scraping-virtuale
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
virtuale_dl-0.1.0.tar.gz -
Subject digest:
0b496a0af5053a6601280bd1256b96b67d35b184c99b16a6e7bbe024f9421b55 - Sigstore transparency entry: 1206233338
- Sigstore integration time:
-
Permalink:
g-mainardi/scraping-virtuale@c4a8d305f3e684caf36661a43b9d056128d317be -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/g-mainardi
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@c4a8d305f3e684caf36661a43b9d056128d317be -
Trigger Event:
push
-
Statement type:
File details
Details for the file virtuale_dl-0.1.0-py3-none-any.whl.
File metadata
- Download URL: virtuale_dl-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b395be1e2781d7841ada0285091a886da2b9389020dcf537c5f8c7152154bbde
|
|
| MD5 |
e82f96fa79b944e74fb564d6dd43b496
|
|
| BLAKE2b-256 |
8e6536e2aab2410440efe3f29562d97465681fc26c1c79ccd28f11083639147d
|
Provenance
The following attestation bundles were made for virtuale_dl-0.1.0-py3-none-any.whl:
Publisher:
release.yml on g-mainardi/scraping-virtuale
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
virtuale_dl-0.1.0-py3-none-any.whl -
Subject digest:
b395be1e2781d7841ada0285091a886da2b9389020dcf537c5f8c7152154bbde - Sigstore transparency entry: 1206233461
- Sigstore integration time:
-
Permalink:
g-mainardi/scraping-virtuale@c4a8d305f3e684caf36661a43b9d056128d317be -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/g-mainardi
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@c4a8d305f3e684caf36661a43b9d056128d317be -
Trigger Event:
push
-
Statement type: