Matching students in Google Classroom when their email is hidden
Google hides personal @gmail.com students' email addresses from the Classroom API by default. Here's what the API actually returns, why, and how Sheet2Classroom matches them anyway.
If you've built anything against the Google Classroom API and tried to match a student to an external data source by email, you've probably seen this: for some students, profile.emailAddress comes back as an empty string or null. Every time. It isn't a bug, and it isn't fixable by changing scopes. This post explains why, what the API actually returns, and the three strategies Sheet2Classroom uses to match students anyway.
What the API returns
A typical call to courses.students.list returns an array of Student objects. Each has a userId and a nested profile object. For a Workspace-for-Education student — say alice.chen@uni.edu — the response includes profile.emailAddress: "alice.chen@uni.edu" and profile.name.fullName: "Alice Chen".
For a student signed in with a personal Google account — say achen.personal@gmail.com — the same call returns profile.emailAddress: "" (empty string) and profile.name.fullName: "Alice Chen". Same field shape, same userId format, but the email field is blank.
This behavior is stable across classroom.profile.emails, classroom.rosters.readonly, and classroom.rosters. Adding more scopes does not unlock the email. The field is empty because Google's privacy model treats personal Gmail accounts as individuals who opted out of sharing their email with third-party apps in the institutional context.
Why this is a privacy feature, not a bug
A Google Workspace for Education account belongs to an institution. The admin of that domain can share members' email addresses with third-party integrations (Sheet2Classroom, Flubaroo, anything else) because the admin has legal authority to do so on behalf of the organization.
A personal Gmail account belongs to a person. Even if that person has accepted an invite to a Classroom course, they have notgiven the teacher or any third-party app permission to expose their email address outside of Classroom's first-party UI. So when a third-party app asks the API for the email, Google refuses. TheuserId is returned (useful for writing grades back) but the email is withheld.
This design is consistent with Google's API Services User Data Policy's Limited Use requirements. It's not something to work around; it's something to work with.
How Sheet2Classroom matches anyway
Matching a sheet row to a Classroom student doesn't have to go through email. We use a three-stage pipeline that falls back only if the previous stage didn't produce a match. Stages run in order of confidence.
Stage 1: Email (highest confidence)
If the sheet has an email column and the roster has an email for that student (Workspace students), exact string equality wins. Normalize both sides to lowercase and trim whitespace before comparison. This catches 90%+ of matches at a typical institution.
Stage 2: Roll number / email prefix
Most school email conventions embed a student ID in the prefix: 21B0123@uni.edu, jdoe2025@school.org, smith.alice@college.edu. If the teacher's sheet has a column with 21B0123 in it (common — roll numbers are what student IDs are called in most South Asian institutions), Sheet2Classroom matches it against the prefix of every email in the roster.
This stage alsofails for personal-Gmail students, because the email field is empty — there's no prefix to match against. But it catches cases where a Workspace student's sheet row uses just the student ID instead of the full email address.
Stage 3: Name (fuzzy, the safety net)
This is the stage that catches personal-Gmail students. profile.name.fullNameis exposed by the API for every student, regardless of account type. So if the teacher's sheet has a name column (or even a cell in a generic identifier column that looks like a name), we compare it against the roster's full names.
Matching rules, in order of strictness:
- Exact normalized equality: both sides lowercased, whitespace collapsed to single spaces. "Alice Chen" matches "alice chen" matches "ALICE CHEN".
- Token-subset: if exact fails, check that every word in the sheet name appears as an exact token in a student's full name. "Alice Chen" matches "Alice May Chen" (the sheet has 2 of the 3 tokens). Prevents false positives on unrelated students who share only a first or last name.
If a sheet name matches exactly one student, we treat it as a valid match and push the grade. If it matches two or more students (two students named "John Smith" in the same class), we flag the row as ambiguous-name and surface a dropdown in the preview UI for the teacher to pick the right one manually.
What other tools do wrong
Faced with the hidden-email problem, many third-party tools go in the opposite direction: they ask for broader scopes, or push the teacher to paste the list of student emails into the spreadsheet "manually." Both approaches violate Google's Limited Use policy:
- Requesting the full
classroom.rostersscope (read/write, not just read) to "work around" the email visibility isn't actually a workaround — the write scope doesn't grant access to data the read scope doesn't. It just inflates the consent screen with permissions the app doesn't need. - Telling teachers to "just paste all your students' emails into column A" asks them to distribute sensitive student data outside the Classroom UI — into a sheet that may be shared with TAs, backed up to personal Drive, or exported. That's a data-handling violation the school's privacy officer should care about.
Name matching requires no extra scope, moves no sensitive data outside Classroom, and works regardless of whether the student chose a personal or institutional account. It's the option Google intended third-party tools to use.
What this means for you as a teacher
When you set up a Sheet2Classroom push:
- If your class is all Workspace accounts, email matching alone is fine.
- If any students signed in with personal Gmail, add a Name column to your sheet and map it in the wizard. Sheet2Classroom uses it as a fallback for the hidden-email rows.
- If your class has duplicate student names, expect the "unmatched" section of the preview to show those rows with a dropdown to pick the correct student.
Try it
The three-stage matcher is the backbone of Sheet2Classroom. It runs in a few milliseconds over the full roster, shows you exactly how each row was matched (email / roll / name / manual) in the preview, and never pushes a grade without a confident match. Free, no Drive scope, no pasting emails anywhere.