If you use the Microsoft Teams PWA (installed via Edge) instead of the native Teams desktop app, clicking Teams meeting join links doesn't work. Here's why:
- The interstitial uses the wrong protocol — meeting links go through a
launcher page that fires
msteams://URLs, but the PWA only registersweb+msteams://. - PWAs can't receive protocol URLs — even if you register the scheme,
Chromium's
app_mode_loaderdoesn't pass protocol URLs to the web content. The PWA just opens to its home page. - Direct
/meet/URLs redirect to the launcher — navigating toteams.cloud.microsoft/meet/IDtriggers a server-side redirect back to the launcher interstitial, creating a loop.
A small AppleScript app (TeamsURLHandler.app) that bridges the gap:
- Registers as the macOS handler for
msteams://URLs - Translates the protocol URL to a web path — strips the
msteams:/prefix and adds&webjoin=true(which tells Teams to handle the join in-browser instead of redirecting to the launcher) - Injects JavaScript into the running Teams PWA — uses
window.location.assign()via AppleScript to navigate the PWA's SPA router directly - Deduplicates — the interstitial fires
msteams://multiple times per click; the handler skips duplicates within 30 seconds
Click meeting link in browser
→ Edge loads interstitial at teams.microsoft.com/dl/launcher/launcher.html
→ Interstitial fires msteams://meet/ID?p=PASSCODE&...
→ macOS routes to TeamsURLHandler.app
→ Handler finds Teams PWA window (single-tab Edge window at teams.cloud.microsoft)
→ Executes: window.location.assign('/meet/ID?p=PASSCODE&webjoin=true')
→ Teams SPA router loads the meeting pre-join screen
- macOS (tested on Tahoe/26.x)
- Microsoft Edge with the Teams PWA installed from
teams.cloud.microsoft - Edge setting: View → Developer → Allow JavaScript from Apple Events must be enabled
The source is in source.applescript.
osacompile -o ~/Applications/TeamsURLHandler.app source.applescriptAdd the msteams:// URL scheme, set the bundle identifier, and make it
background-only (no Dock icon):
APP=~/Applications/TeamsURLHandler.app/Contents/Info.plist
/usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes array" "$APP"
/usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes:0 dict" "$APP"
/usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes:0:CFBundleURLName string com.ewj.teamsurlhandler.msteams" "$APP"
/usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes:0:CFBundleURLSchemes array" "$APP"
/usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes:0:CFBundleURLSchemes:0 string msteams" "$APP"
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier com.ewj.teamsurlhandler" "$APP"
/usr/libexec/PlistBuddy -c "Add :LSBackgroundOnly bool true" "$APP"codesign --force --sign - ~/Applications/TeamsURLHandler.app
LSREG=/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister
$LSREG -f ~/Applications/TeamsURLHandler.app
swift -e '
import CoreServices; import Foundation
LSSetDefaultHandlerForURLScheme(
NSString(string:"msteams") as CFString,
NSString(string:"com.ewj.teamsurlhandler") as CFString
)'Suppress the "Open this app?" prompt when Edge fires msteams://:
defaults write com.microsoft.Edge AutoLaunchProtocolsFromOrigins \
-string '[{"protocol":"msteams","allowed_origins":["teams.microsoft.com","*.teams.microsoft.com","teams.cloud.microsoft","*.teams.cloud.microsoft"]}]'# Check the handler is registered
swift -e 'import AppKit; print(NSWorkspace.shared.urlForApplication(toOpen: URL(string:"msteams://test")!)!)'
# Should print: file:///Users/YOU/Applications/TeamsURLHandler.app/
# Test it
open "msteams://meet/123?p=test&anon=true"
# Should open the Teams PWA to the meeting pre-join screen- If your Teams PWA is at a different path (e.g., you renamed it), edit the
do shell script "open ..."line insource.applescriptand recompile. - If you use Chrome instead of Edge, change
tell application "Microsoft Edge"totell application "Google Chrome"(the AppleScript API is identical).
- View the debug log:
tail -f ~/Library/Logs/TeamsURLHandler.log - PWA shows a spinner: The interstitial may have fired multiple times. The dedup logic should prevent this, but if it persists, wait ~10 seconds for the SPA to finish loading.
- Handler stops working after Edge update: Re-run steps 3 (sign and register) above.
- "Allow JavaScript from Apple Events" prompt: This is required for the handler to inject navigation into the PWA. Enable it once in Edge's View → Developer menu.
webjoin=trueis the magic query parameter that tells Teams to handle meeting joins in the web client rather than redirecting to the launcher.msteams://≠web+msteams://— the interstitial uses the former, the PWA only registers the latter. They're different URL schemes.- JavaScript
location.assign()is the only reliable navigation method — AppleScriptset URL of tand Edge's--app-launch-urlflag both fail due to PWA scope restrictions and server-side redirects.