How does Canvas handle SCORM?
Canvas has no SCORM runtime of its own. SCORM in Canvas runs through an external tool that an administrator enables, which adds a SCORM link to course navigation. You upload the zip there and choose how it lands: a graded assignment, an ungraded assignment, or a page. That one choice decides whether anything reaches the gradebook.
Everything else follows from that split. The package reports what SCORM packages report — status, score, a bookmark. Canvas records what Canvas records — a submission on an assignment, a number in a column, a module requirement met or not. The external tool sits between the two and translates. Most Canvas SCORM problems are not broken packages; they are a package reporting one thing and a Canvas object built to hold something else.
The external-tool route
If there is no SCORM item in your course navigation, the tool is not enabled for your institution or not turned on for your course. An admin enables it at the account level; you then make it visible under Settings > Navigation. No amount of rebuilding the package will conjure the link.
The tool is a player with its own runtime, not a Canvas feature that happens to read zips. Your content is launched inside it, and the tool — not Canvas — answers the Initialize, SetValue and Commit calls the SCO makes. Canvas only ever sees the summary the tool hands back. That is the same shape as any LTI integration, and it is worth understanding the difference before you choose a delivery route at all; LTI vs SCORM covers where each one belongs.
Canvas SCORM implementations commonly accept SCORM 1.2 and SCORM 2004 (2nd, 3rd and 4th editions), so unlike platforms locked to 1.2 you have a real choice. Pick the version for the reporting you need, not for the year it was published.
Setting up a package
Three things have to be true of the file before you upload it:
- It is a
.zip, andimsmanifest.xmlis at the root. Zipping the folder instead of its contents puts the manifest one level down, and the import fails or produces an item that will not launch. - It is inside the portal's upload ceiling. That ceiling is an institutional setting, not a SCORM one, and it varies between universities. Find your own number before you spend a day rendering video into a package that cannot be uploaded.
- Nothing in it depends on Flash. Flash was disabled everywhere at the end of 2020. Legacy courses built around it will import cleanly and then show a blank frame.
Open the SCORM link, upload the zip, and pick the import type when prompted. The three options behave differently in ways that are hard to undo:
| Import as | What Canvas creates | Gradebook |
|---|---|---|
| Graded assignment | An unpublished assignment, typically worth 100 points by default, with the External Tool submission type already set | Score passes through |
| Ungraded assignment | An unpublished assignment worth 0 points | Score does not pass through |
| Page (learning resource) | A page you can embed in a module | No gradebook path at all |
Two consequences catch people out. The import type generally cannot be switched afterwards — changing it means deleting the content and uploading it again, which also discards whatever attempts existed. And the assignment Canvas creates is unpublished: it exists, it looks fine to you, and no student can see it until you publish it and place it in a module.
Completion and the gradebook
SCORM carries two separate ideas. Completion status answers "did the learner reach the end". Success status answers "did they pass". A learner can be completed and failed at the same time, because both are true. Completion vs success unpacks the data model.
A Canvas gradebook column holds one number. So the translation is lossy in a specific, predictable direction: a package that sets cmi.core.lesson_status or cmi.completion_status and never writes a score has given the tool nothing numeric to hand over. The attempt is recorded; the column stays empty; the module requirement that was waiting on a score never fires. This is the single most common "SCORM is not working in Canvas" report, and the package is behaving exactly as built.
Match what the package sends to what you want Canvas to do:
| What you want | What the package must send |
|---|---|
| A grade in the column | A score — cmi.core.score.raw in 1.2, or cmi.score.raw and cmi.score.scaled in 2004 — written and committed |
| A pass/fail distinction | Success status, separate from completion status; on 1.2 that means using passed / failed rather than completed |
| A module gate on "score at least X" | A score, because Canvas module requirements read the Canvas assignment, not the SCORM record |
| A module gate with no assessment in the content | Nothing from the package — use the "view" requirement on the item instead, and accept that it proves only that the page was opened |
Write the values in this order at the end of an attempt, and commit before terminating:
SetValue("cmi.core.score.raw", "82")
SetValue("cmi.core.lesson_status", "passed")
Commit("")
Terminate("")
Score first, then status. Some platforms freeze the record at the first completion they see and discard a score that arrives afterwards.
Known limitations
None of these are faults in your package. They are the shape of the integration, and knowing them up front saves a rebuild:
- One score per item. A multi-SCO manifest still has to resolve to a single value before Canvas can store it. Where a grade matters, a single-SCO package is the predictable build.
- Import type is effectively permanent. Correcting it means a delete and re-upload, and re-uploading creates a new item — existing attempts do not follow it across.
- Suspend data caps still apply. 4 KB in SCORM 1.2, 64 KB in 2004. A long course that stores every answer in the bookmark string will silently truncate and resume into corrupted state.
- Launching inline constrains the content. Content rendered inside the Canvas frame inherits the frame's width and scrolling behaviour; opening in a new tab avoids that but puts the content at the mercy of popup blockers.
- Preview is not a submission. Looking at the content as an instructor does not create the student-side record the gradebook needs, so it cannot prove the grade path works.
Testing the flow
Test with a genuinely enrolled test student, on the published assignment, launching the way your learners will. Then walk the whole path rather than the happy half of it:
- Launch and confirm the session starts. If the content cannot find the API object because of the launch method or a blocked window, every later call is void — and the learner still has a completely normal experience while nothing is recorded.
- Finish the course properly, then close the tab abruptly instead of using the exit button. This one step catches more lost completions than any other test, because a package that only saves on a clean exit loses everything when someone closes the window.
- Check the gradebook, not the tool's own report. The tool knowing the score and Canvas holding it are two different facts.
- Deliberately fail. Confirm a failed attempt looks different from a passed one in the column. If both read the same, your package is reporting completion where it should be reporting success.
- Relaunch and confirm resume. The bookmark and the status should both have survived.
Run those checks against the package before it goes near a live section — testing SCORM before upload covers driving the same sequence outside an LMS, where the runtime log is visible and a failure costs you a minute instead of a cohort. What the gradebook shows is the honest record: what Canvas received, not what the course appeared to do. If a value is not there, the content never sent it, and no course setting will conjure it.
Where SCORM Central fits
SCORM Central converts files you already have — PDF, PowerPoint, Word, or video — into SCORM 1.2, SCORM 2004, cmi5, or xAPI, and shows you the manifest, the full runtime log, and a conformance report on every build, so you can see exactly what a package will report before an LMS does. See how it works, or start with one file.