Python CLI and library for automating Moodle through real web sessions, with CAS/SSO support and no custom plugins required.
- No API token required — works with standard Moodle login and CAS/SSO
- Works with web sessions — simulates a real user browser session, no Moodle plugins needed
- CLI for admins and library for automation scripts
- Handles courses, sections, labels, folders, assignments and SCORM out of the box
- Tested against Moodle 4.x and 5.x on Python 3.8–3.13
| Capability | python-moodle | Moodle webservice wrappers |
|---|---|---|
| No custom plugin required | ✅ Yes | Usually yes/no |
| Works with real web sessions | ✅ Yes | ❌ No |
| CAS/SSO support | ✅ Yes | Usually limited |
| CLI included | ✅ Yes | Often no |
| SCORM/course admin workflows | ✅ Yes | Varies |
pip install python-moodle
cp .env.example .env
# Edit .env with your Moodle URL and credentials
py-moodle courses list| Task | Command / Use case |
|---|---|
| Bulk course creation | py-moodle courses create |
| SCORM upload pipelines | py-moodle modules add scorm |
| Content migration | Script with list_courses + create_course |
| Moodle smoke tests in CI | pytest + MoodleSession fixture |
| Admin scripting across instances | --env flag with multiple .env profiles |
!!! warning "Experimental" This library is under active development. Use a test Moodle instance and back up data before running commands that create, modify, or delete content.
py-moodle allows you to automate tedious Moodle tasks—like creating courses, uploading content, and managing modules—directly from your terminal or in your Python scripts. It works by simulating a real user's web session, so it doesn't require API tokens or special Moodle plugins.
- Manage Moodle entities: Courses, sections, users, and modules from the command line.
- Rich module support: Includes built-in support for Folders, Labels, Assignments, and SCORM packages.
- Session-based: Works with standard Moodle web sessions, avoiding the need for web service tokens.
- Authentication: Supports standard Moodle login and SSO/CAS authentication.
- Dual Use: Can be used as a powerful CLI or imported as a library into your own Python projects.
- Extensible: Designed to be easily extended with new modules and commands. See
AGENTS.md. - English-only codebase: For clear, global collaboration.
py-moodle interacts with Moodle through authenticated web sessions, HTML forms, and page parsing. To make those flows more resilient across Moodle releases, the library now centralizes version-sensitive logic in py_moodle.compat.
- Version detection happens during login/session initialization. The library first tries
core_webservice_get_site_infowhen a webservice token is available, then falls back to probing the dashboard HTML (/my/) for Moodle release metadata. - Version-aware strategies are grouped into compatibility ranges instead of scattering selectors throughout the codebase. The current built-in strategies cover legacy Moodle 3.x layouts and modern Moodle 4.x/5.x layouts.
- Feature probing remains in place when version detection is not enough. Each strategy can try multiple selectors or form patterns before failing.
- Fragile flows should read selectors from the compatibility layer so future Moodle HTML changes are isolated to one module.
At the moment, representative compatibility handling has been wired into login/session bootstrap, generic module form parsing, and folder page scraping. When a new Moodle release changes one of these flows, the recommended fix is to update py_moodle.compat and add a regression test for the new selector or workflow.
You will need Python 3.8+ and pip.
pip install python-moodleClone the repository and install:
git clone https://github.com/erseco/python-moodle.git
cd python-moodle
pip install .Copy the example .env.example file to .env and add your Moodle instance credentials.
cp .env.example .env
# Now, edit the .env file with your credentials!!! danger
The .env file stores real credentials. Keep it out of version control and share it with no one.
Your .env file should look like this:
# Production environment credentials
MOODLE_PROD_URL=https://your.moodle.site
MOODLE_PROD_USERNAME=your_admin_user
MOODLE_PROD_PASSWORD=your_super_secret_password
# Optional: CAS SSO URL
# MOODLE_PROD_CAS_URL=https://cas.your-institution.org/cas
# Optional: Predefined webservice token (required for CAS)
# MOODLE_PROD_WS_TOKEN=your_webservice_tokenUse the --env flag or the MOODLE_ENV variable to select the environment, e.g. py-moodle --env prod courses list.
Note: For local development, you can quickly spin up a Moodle instance using the provided
docker-compose.yml:docker-compose up -d.
Once installed, all functionality is available through the py-moodle command. Every command and subcommand includes detailed help with the -h or --help flag.
Here are a few examples of common commands:
List all available courses:
py-moodle courses listOutput:
┏━━━━┳━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━┓
┃ ID ┃ Shortname ┃ Fullname ┃ Category ┃ Visible ┃
┡━━━━╇━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━┩
│ 2 │ my-first-course │ My first course │ 1 │ 1 │
│ 4 │ my-second-course │ My second course │ 1 │ 1 │
└────┴────────────────────┴────────────────────┴──────────┴─────────┘
Show the structure of a single course:
py-moodle courses show 2Create a new course:
py-moodle courses create --fullname "My New Automated Course" --shortname "auto-course-01"Add a label to a course section:
py-moodle modules add label --course-id 2 --section-id 1 --name "Welcome" --intro "<h1>Welcome to the course!</h1>"Upload a SCORM package to a course:
py-moodle modules add scorm --course-id 2 --section-id 1 --name "My SCORM Package" --path "path/to/your/scorm.zip"You can also import py-moodle's functions into your own Python scripts to automate complex workflows. The example_script.py file provides a comprehensive tutorial.
from py_moodle import MoodleSession
from py_moodle.course import list_courses
# Credentials are loaded automatically from your .env file
ms = MoodleSession.get()
courses = list_courses(ms.session, ms.settings.url, token=ms.token)
for course in courses:
print(course["id"], course["fullname"])The script is a self-contained demonstration that:
- Logs into Moodle using the credentials from your
.envfile. - Creates a new, temporary course.
- Populates the course with sections, labels, assignments, and a SCORM package.
- Creates a folder and uploads multiple files to it.
- Prints a summary of the final course structure.
- Automatically cleans up and deletes the course and all its contents.
Make sure you have a valid .env file and have installed the dependencies. Then, simply run:
python example_script.pyThis script is the best starting point for understanding how to use the library's functions for your own automation needs.
The project uses pytest and provides a Makefile with convenient targets.
Run the fast smoke test suite (no Moodle service required):
make test-unitRun the Docker-backed integration suite against the local environment:
make test-localRun tests against the staging environment:
make test-stagingRun all configured environments:
make testGitHub Actions automatically runs:
- linting on Python 3.13
- smoke tests on Python 3.8 through 3.13
- Docker-backed integration tests on representative Python/Moodle combinations:
- Python 3.8 with Moodle 4.5.5
- Python 3.13 with Moodle 5.0.1
Use the Makefile to format code, run linters, or build the documentation:
make format # run black and isort
make lint # run static analysis
make docs # build the MkDocs siteDocumentation is generated with MkDocs using the Read the Docs theme and published automatically to the gh-pages branch.
Every push to main builds the API reference and CLI guide from the source code and makes it available via GitHub Pages.
To build the documentation locally:
pip install mkdocs 'mkdocstrings[python]'
mkdocs build --strictThe rendered site will be available under the site/ directory.
Contributions are welcome! Please follow the guidelines outlined in [AGENTS.md]. Key principles include:
- All code, comments, and documentation must be in English.
- Code must be formatted with
blackand linted withflake8. - Docstrings must use the Google style;
flake8-docstringsis configured for this convention. - The CLI should be a thin layer over the core library functions.
- All new features must be accompanied by tests.
This project is licensed under the MIT License.