To integrate Replit with Google Classroom, create a Google Cloud project, enable the Classroom API, and set up OAuth 2.0 credentials. Store your Client ID and Client Secret in Replit Secrets (lock icon 🔒 in sidebar), then use the Google Classroom REST API from your Node.js or Python backend to read courses, assignments, and submissions. A deployed Replit server is required to handle the OAuth redirect callback.
Why Integrate Google Classroom with Replit?
Google Classroom is used by hundreds of millions of students and teachers worldwide. The Classroom API lets developers build tools that extend Classroom's functionality: automated assignment distribution, grade export scripts, custom dashboards that aggregate submission data across multiple classes, attendance tools, and parent notification systems. Replit is an ideal platform for hosting these tools because it provides a persistent web server with a public URL — something required for the OAuth 2.0 redirect flow that Classroom authentication depends on.
The Google Classroom API is a RESTful API with clear resource types: courses, coursework (assignments and materials), submissions, announcements, and roster (teachers and students). Once a user completes the OAuth flow, your Replit app can act on their behalf — reading their course list, fetching assignment details, checking which students submitted, and programmatically posting grades.
Common use cases for Replit and Google Classroom integration include: building a teacher dashboard that shows all pending grading across multiple courses in one view, creating automated quiz scoring tools that sync results back to Classroom gradebooks, generating submission reports for administrators, and building parent-facing portals that display assignment status for a student's courses.
Integration method
The Replit-Google Classroom integration uses Google's OAuth 2.0 Authorization Code flow. Your Replit app registers a redirect URI in the Google Cloud Console, sends users to Google's consent screen, receives an authorization code at the redirect endpoint, exchanges it for access and refresh tokens, and then calls the Classroom API on behalf of the authenticated user. Tokens are stored server-side in Replit; the frontend only sees session IDs.
Prerequisites
- A Google account with access to Google Classroom courses (teacher or admin role for most write operations)
- A Google Cloud project with billing enabled (free tier is sufficient for Classroom API)
- Google Classroom API enabled in the Google Cloud Console
- OAuth 2.0 credentials (Client ID and Client Secret) configured with your Replit app's URL as the redirect URI
- A deployed Replit app with a public URL (required for OAuth redirect)
Step-by-step guide
Create a Google Cloud Project and Enable the Classroom API
Create a Google Cloud Project and Enable the Classroom API
Go to console.cloud.google.com and sign in. Click 'Select a project' at the top, then 'New Project'. Give it a name like 'Classroom Replit Integration' and click 'Create'. Once the project is created, navigate to 'APIs & Services' → 'Library'. Search for 'Google Classroom API'. Click on it and click 'Enable'. Next, configure the OAuth consent screen. Go to 'APIs & Services' → 'OAuth consent screen'. Choose 'External' (for Google accounts outside your organization) or 'Internal' (for Google Workspace accounts in your domain). Fill in the required fields: - App name: your application name - User support email: your email - Developer contact: your email Under 'Scopes', add the Classroom API scopes your app needs: - https://www.googleapis.com/auth/classroom.courses.readonly — read course list - https://www.googleapis.com/auth/classroom.coursework.me.readonly — read your assignments - https://www.googleapis.com/auth/classroom.rosters.readonly — read class roster - https://www.googleapis.com/auth/classroom.student-submissions.me.readonly — read submissions For write operations (posting grades, creating announcements), add the corresponding write scopes. Click 'Save and Continue' through all steps. Your app will be in 'Testing' mode, which allows up to 100 test users. Add your own Google account as a test user.
Pro tip: During development, add your own Google account as a test user in the OAuth consent screen. Without this, the OAuth flow will fail with 'Access blocked: This app's request is invalid'.
Expected result: The Google Classroom API is enabled in your project and the OAuth consent screen is configured with the required scopes.
Create OAuth 2.0 Credentials
Create OAuth 2.0 Credentials
In the Google Cloud Console, go to 'APIs & Services' → 'Credentials'. Click '+ Create Credentials' → 'OAuth client ID'. Choose 'Web application' as the application type. Give it a name (e.g., 'Replit Web Client'). Under 'Authorized redirect URIs', add your Replit app's callback URL. The format is: https://your-repl-name.your-username.repl.co/auth/google/callback To find your Replit app URL before deploying: open your Repl, click the web preview panel, and copy the URL shown. Your callback path must match exactly what you will configure in your Express/Flask server. Click 'Create'. Google shows your Client ID and Client Secret — copy both immediately. The Client Secret is shown once in this screen; you can retrieve it later from the credentials list but it is easier to copy now. Store these in Replit Secrets in the next step. Do not paste them into your code files.
Pro tip: If your Replit app URL changes (e.g., after forking the Repl), you must update the authorized redirect URI in Google Cloud Console. OAuth will fail with 'redirect_uri_mismatch' if the URLs do not match exactly.
Expected result: You have a Google OAuth Client ID (ends in .apps.googleusercontent.com) and Client Secret ready to store in Replit Secrets.
Store Credentials in Replit Secrets
Store Credentials in Replit Secrets
Click the lock icon (🔒) in the Replit sidebar. Add the following secrets: GOOGLE_CLIENT_ID — your OAuth Client ID GOOGLE_CLIENT_SECRET — your OAuth Client Secret GOOGLE_REDIRECT_URI — your full callback URL (e.g., https://your-repl.your-user.repl.co/auth/google/callback) SESSION_SECRET — a random string used to sign session cookies (generate with: require('crypto').randomBytes(32).toString('hex')) These values must never appear in your code. The CLIENT_SECRET in particular authenticates your application to Google — if exposed, anyone could impersonate your app in the OAuth flow.
Pro tip: Generate a secure SESSION_SECRET by running this in the Replit Shell: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" and storing the output as the secret.
Expected result: GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GOOGLE_REDIRECT_URI, and SESSION_SECRET all appear in the Replit Secrets panel.
Implement OAuth 2.0 Flow and Call the Classroom API (Node.js)
Implement OAuth 2.0 Flow and Call the Classroom API (Node.js)
Install the required packages: npm install express express-session googleapis The googleapis package provides the official Google API client for Node.js, which handles OAuth token exchange and API calls. The flow is: 1. User visits /auth/login → redirected to Google's consent screen 2. User grants permission → Google redirects to /auth/google/callback with an authorization code 3. Server exchanges the code for tokens → stores tokens in session 4. Server uses tokens to call Classroom API Tokens expire after 1 hour but include a refresh token for automatic renewal.
1// server.js — Google Classroom OAuth + API server2const express = require('express');3const session = require('express-session');4const { google } = require('googleapis');56const app = express();7app.use(express.json());8app.use(session({9 secret: process.env.SESSION_SECRET,10 resave: false,11 saveUninitialized: false12}));1314function getOAuthClient() {15 return new google.auth.OAuth2(16 process.env.GOOGLE_CLIENT_ID,17 process.env.GOOGLE_CLIENT_SECRET,18 process.env.GOOGLE_REDIRECT_URI19 );20}2122const SCOPES = [23 'https://www.googleapis.com/auth/classroom.courses.readonly',24 'https://www.googleapis.com/auth/classroom.coursework.me.readonly',25 'https://www.googleapis.com/auth/classroom.rosters.readonly'26];2728// Step 1: redirect to Google consent screen29app.get('/auth/login', (req, res) => {30 const oauth2Client = getOAuthClient();31 const authUrl = oauth2Client.generateAuthUrl({32 access_type: 'offline', // Get refresh token33 scope: SCOPES,34 prompt: 'consent'35 });36 res.redirect(authUrl);37});3839// Step 2: handle the callback from Google40app.get('/auth/google/callback', async (req, res) => {41 const { code } = req.query;42 if (!code) return res.status(400).send('Missing authorization code');4344 try {45 const oauth2Client = getOAuthClient();46 const { tokens } = await oauth2Client.getToken(code);47 req.session.tokens = tokens;48 res.redirect('/courses'); // Redirect to app after login49 } catch (err) {50 console.error('OAuth callback error:', err.message);51 res.status(500).send('Authentication failed');52 }53});5455// Middleware: check authentication56function requireAuth(req, res, next) {57 if (!req.session.tokens) return res.redirect('/auth/login');58 next();59}6061// Step 3: use the token to call Google Classroom API62app.get('/courses', requireAuth, async (req, res) => {63 try {64 const oauth2Client = getOAuthClient();65 oauth2Client.setCredentials(req.session.tokens);6667 const classroom = google.classroom({ version: 'v1', auth: oauth2Client });68 const response = await classroom.courses.list({69 pageSize: 20,70 courseStates: ['ACTIVE']71 });7273 const courses = (response.data.courses || []).map(c => ({74 id: c.id,75 name: c.name,76 section: c.section,77 enrollmentCode: c.enrollmentCode,78 courseState: c.courseState79 }));8081 res.json({ courses });82 } catch (err) {83 console.error('Classroom API error:', err.message);84 res.status(500).json({ error: err.message });85 }86});8788// Fetch assignments for a course89app.get('/courses/:courseId/assignments', requireAuth, async (req, res) => {90 const { courseId } = req.params;91 try {92 const oauth2Client = getOAuthClient();93 oauth2Client.setCredentials(req.session.tokens);9495 const classroom = google.classroom({ version: 'v1', auth: oauth2Client });96 const response = await classroom.courses.courseWork.list({97 courseId,98 pageSize: 50,99 orderBy: 'dueDate asc'100 });101102 res.json({ assignments: response.data.courseWork || [] });103 } catch (err) {104 res.status(500).json({ error: err.message });105 }106});107108const PORT = process.env.PORT || 3000;109app.listen(PORT, '0.0.0.0', () => {110 console.log(`Google Classroom server running on port ${PORT}`);111});Pro tip: Set access_type: 'offline' and prompt: 'consent' in the auth URL generation to always receive a refresh token. Without a refresh token, your server will fail after the access token expires (1 hour).
Expected result: Visiting /auth/login redirects to Google's consent screen. After authorization, visiting /courses returns a list of active Google Classroom courses as JSON.
Python Implementation with Flask
Python Implementation with Flask
For Python Replit projects, the google-auth-oauthlib and google-api-python-client libraries provide the same OAuth and Classroom API functionality. Install: pip install flask google-auth-oauthlib google-api-python-client The Python implementation follows the same OAuth flow as the Node.js version but uses Flask's session for token storage.
1# app.py — Google Classroom OAuth server in Python2import os3import json4from flask import Flask, session, redirect, url_for, request, jsonify5from google_auth_oauthlib.flow import Flow6from googleapiclient.discovery import build7from google.oauth2.credentials import Credentials89app = Flask(__name__)10app.secret_key = os.environ['SESSION_SECRET']11os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '0' # Enforce HTTPS in production1213SCOPES = [14 'https://www.googleapis.com/auth/classroom.courses.readonly',15 'https://www.googleapis.com/auth/classroom.coursework.me.readonly'16]1718def make_flow():19 return Flow.from_client_config(20 {21 'web': {22 'client_id': os.environ['GOOGLE_CLIENT_ID'],23 'client_secret': os.environ['GOOGLE_CLIENT_SECRET'],24 'redirect_uris': [os.environ['GOOGLE_REDIRECT_URI']],25 'auth_uri': 'https://accounts.google.com/o/oauth2/auth',26 'token_uri': 'https://oauth2.googleapis.com/token'27 }28 },29 scopes=SCOPES,30 redirect_uri=os.environ['GOOGLE_REDIRECT_URI']31 )3233@app.route('/auth/login')34def login():35 flow = make_flow()36 auth_url, state = flow.authorization_url(access_type='offline', prompt='consent')37 session['oauth_state'] = state38 return redirect(auth_url)3940@app.route('/auth/google/callback')41def callback():42 flow = make_flow()43 flow.fetch_token(authorization_response=request.url)44 creds = flow.credentials45 session['tokens'] = {46 'token': creds.token,47 'refresh_token': creds.refresh_token,48 'token_uri': creds.token_uri,49 'client_id': creds.client_id,50 'client_secret': creds.client_secret,51 'scopes': list(creds.scopes)52 }53 return redirect('/courses')5455@app.route('/courses')56def courses():57 if 'tokens' not in session:58 return redirect('/auth/login')59 creds = Credentials(**session['tokens'])60 service = build('classroom', 'v1', credentials=creds)61 result = service.courses().list(pageSize=20, courseStates=['ACTIVE']).execute()62 return jsonify({'courses': result.get('courses', [])})6364if __name__ == '__main__':65 app.run(host='0.0.0.0', port=3000)Pro tip: Set OAUTHLIB_INSECURE_TRANSPORT='0' in production. During local dev on Replit you may set it to '1' temporarily if testing over HTTP, but the deployed Replit URL uses HTTPS so this should not be needed.
Expected result: Visiting /auth/login in the browser triggers Google OAuth. After consent, /courses returns the authenticated user's active Google Classroom courses.
Common use cases
Multi-Course Assignment Dashboard
Build a teacher tool that lists all courses, then shows all pending assignments across every course in a single view, sorted by due date. Teachers currently have to click into each course separately in Classroom — this dashboard saves significant time.
Build a Node.js Express server with Google OAuth 2.0 login. After login, fetch all the teacher's courses from the Classroom API, then for each course fetch all coursework with a due date. Display them sorted by due date ascending. Store GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET in environment variables.
Copy this prompt to try it in Replit
Assignment Submission Status Exporter
Create a tool that takes a course ID and assignment ID, fetches all student submissions, and exports a CSV with each student's name, submission status (turned in / not turned in), and grade if assigned. Export it to a file or return it via HTTP.
Write a Python Flask server with Google OAuth that provides a GET /export?courseId=X&assignmentId=Y endpoint. After authentication, fetch all student submissions for that assignment and return a CSV file with student name, email, submission status, and grade. Store OAuth credentials in environment variables.
Copy this prompt to try it in Replit
Automated Course Announcement Sender
Build an internal tool that sends the same announcement to multiple Google Classroom courses at once. Useful for school administrators who need to broadcast a message to all classes, or teachers who manage several sections of the same course.
Create a Node.js server with an endpoint POST /announce that accepts a message and list of course IDs, authenticates via Google OAuth, and posts the message as an announcement to each specified course using the Classroom API. Store credentials in environment variables.
Copy this prompt to try it in Replit
Troubleshooting
redirect_uri_mismatch — OAuth callback returns this error from Google
Cause: The redirect URI your server sends to Google does not exactly match the URI registered in Google Cloud Console. Even a trailing slash difference or http vs https mismatch causes this error.
Solution: In the Google Cloud Console, go to Credentials → your OAuth client → Authorized redirect URIs. Ensure the URI listed exactly matches process.env.GOOGLE_REDIRECT_URI in your Replit Secrets, including protocol, hostname, path, and no trailing slash.
1// Log the exact redirect URI your server is using2console.log('Using redirect URI:', process.env.GOOGLE_REDIRECT_URI);Access blocked: This app's request is invalid — OAuth consent screen error
Cause: Your Google account is not added as a test user in the OAuth consent screen configuration, and the app is still in 'Testing' mode.
Solution: Go to Google Cloud Console → APIs & Services → OAuth consent screen → Test users. Add your Google account email address as a test user. Only test users can authorize apps in Testing mode.
insufficient_scope — Classroom API returns 403 for specific operations
Cause: The OAuth token was granted without including the scope needed for the operation you are trying to perform.
Solution: Add the required scope to the SCOPES array in your authorization URL generation, then re-authorize the user (they will see a new consent screen). Write operations (creating announcements, posting grades) require separate write scopes.
1const SCOPES = [2 'https://www.googleapis.com/auth/classroom.courses.readonly',3 'https://www.googleapis.com/auth/classroom.announcements', // Add write scope4];Token expired — API calls fail after 1 hour with 401 Unauthorized
Cause: Google OAuth access tokens expire after 3600 seconds. Without automatic refresh, API calls fail after expiry.
Solution: The googleapis client for Node.js handles token refresh automatically when you provide a refresh token. Ensure you set access_type: 'offline' when generating the auth URL. For Python, use google.auth.transport.requests.Request() to refresh expired credentials.
1// Node.js: googleapis refreshes automatically if refresh_token is in session2// Ensure you stored the full tokens object including refresh_token3console.log('Has refresh token:', !!req.session.tokens?.refresh_token);Best practices
- Store GOOGLE_CLIENT_SECRET in Replit Secrets and never log it or include it in HTTP responses or error messages
- Request only the OAuth scopes your application actually uses — requesting broader scopes than necessary reduces user trust and may cause the OAuth consent to be rejected
- Store OAuth tokens server-side in the session, never in the browser's localStorage or as cookies accessible to JavaScript
- Set access_type: 'offline' in your auth URL to receive a refresh token — without it, users must re-authorize every hour
- Add your own Google account as a test user while the OAuth app is in Testing mode to avoid 'access blocked' errors
- Deploy as an Autoscale Replit deployment with a stable URL, since the redirect URI must be registered in Google Cloud Console and must not change
- Handle token refresh errors gracefully — when the refresh token is revoked (user revoked app access), redirect to re-authorization rather than showing an error
- Use pagination (nextPageToken) when fetching large course or submission lists to avoid incomplete data
Alternatives
Canvas LMS offers a more comprehensive API for full learning management features including detailed gradebooks and rubrics, making it better for higher education institutions with complex course structures.
Edmodo is a simpler social learning platform with a limited API compared to Google Classroom, but may already be in use by schools that prefer its social network style.
If your primary need is managing video sessions tied to courses rather than assignments and grading, the Google Meet API combined with Google Calendar offers a complementary integration.
Frequently asked questions
How do I connect Replit to Google Classroom?
Create a Google Cloud project, enable the Classroom API, and generate OAuth 2.0 credentials with your Replit app's URL as the redirect URI. Store the Client ID and Client Secret in Replit Secrets, then implement the OAuth 2.0 Authorization Code flow in your Node.js or Python server. After a user authorizes your app, you can call the Classroom API on their behalf.
Does Replit work with the Google Classroom API?
Yes. The Google Classroom API accepts standard HTTPS requests and works with Replit's Node.js and Python environments. Replit is well-suited for Classroom integrations because it provides a persistent public URL needed for the OAuth redirect callback.
Can I use the Google Classroom API for free?
Yes. The Google Classroom API is free to use within Google Cloud's quotas (500 queries per 100 seconds by default). Creating a Google Cloud project and enabling the API costs nothing. The API is available to any Google Workspace or personal Google account with Classroom access.
Do I need a teacher account to use the Classroom API?
It depends on what you want to do. Reading course data, assignments, and submissions requires the account to be enrolled in or teaching those courses. Creating assignments and posting grades requires teacher or co-teacher role. Student accounts can read their own submissions and assignment details.
Why does my OAuth redirect fail in the Replit preview?
The Replit preview window uses an embedded iframe URL that differs from the public Replit URL. Google OAuth requires exact redirect URI matching — it will fail in the in-app preview. Test the OAuth flow by opening your Replit app URL in a full browser tab, not the built-in preview panel.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation