TheNetsky/Microsoft-Rewards-Script

Automated Microsoft Rewards script, using TypeScript and Playwright.

TypeScript

1,107

260 commits

updated Oct 12, 2026

See the code

README

Discord Latest Build Docker

[!TIP] This version supports the new, modern Bing Rewards dashboard only - it does not support the legacy dashboard. If your account still uses the old dashboard, use the v3 branch and v3.x releases instead!

Use at your own risk - some features may not work as expected.


Table of Contents


Quick Setup

Bare metal

Requirements: Node.js >= 24 and Git
Works on Windows, Linux, macOS, and WSL.

Get the script

git clone https://github.com/TheNetsky/Microsoft-Rewards-Script.git
cd Microsoft-Rewards-Script

Or, download the latest release ZIP and extract it.

Account Setup

  • Copy and rename env.example to .env and add your account credentials:
[email protected]
# ACCOUNT_1_PASSWORD=your_password

[!NOTE] ACCOUNT_N_PASSWORD is optional. Set it when password sign-in should be available; leave it unset for passwordless/Authenticator-only accounts.

Add one ACCOUNT_N_* block per account. Account slots do not need to be contiguous: ACCOUNT_2 or ACCOUNT_4 can be configured even when earlier slots are missing. Accounts run in ascending slot order. Optional per-account fields cover recovery email, locale, language, proxy, and fingerprint persistence - see env.example for all of them.

ACCOUNT_N_LANG_CODE accepts a BCP 47 language tag such as nl, it, or pt-BR. ACCOUNT_N_GEO_LOCALE accepts a two-letter country code or defaults to auto. The selected language and country are applied consistently to browser fingerprints, Accept-Language, Microsoft Rewards app headers, and market-specific requests. In auto mode, the country reported by the Microsoft profile is cached after the first successful dashboard request; changing either locale setting automatically replaces an incompatible saved fingerprint.

[!TIP] For 2FA accounts, set ACCOUNT_N_TOTP_SECRET and the script will generate and enter the 6-digit code automatically. To get the secret: in your Microsoft Security settings open 'Manage how you sign in', add an Authenticator app, and when the QR code appears choose 'enter code manually' - use that code as the value in your .env.

[!WARNING] You must rebuild your script after making any changes to the .env.

Config Setup

[!WARNING] Do not skip this step if you are running the script bare metal.

  • Bare metal: Copy or rename config.example.json to config.json (in the project root) and customize your preferences.
  • Docker: A valid config.json is automatically created on first run and saved locally to ./config/. You can optionally manually create a config.json (e.g., if you need to specify regex values) using the provided config.example.json

[!CAUTION] Prior versions of accounts.json and config.json are not compatible with current release.

Build and run the script (bare metal version)

npm run pre-build
npm run build
npm run start

Docker

[email protected]
# ACCOUNT_1_PASSWORD=your_password

ACCOUNT_N_PASSWORD is optional; omit it for passwordless/Authenticator-only accounts.

  • Review compose.yaml to adjust scheduling, timezone, and config options.

[!NOTE] A valid config.json is auto-generated on first run using default values, and saved locally to ./config/. Optionally, use CONFIG_* variables in the environment: section of the compose.yaml to customise your options (e.g., clusters, webhook, etc.). A full list of available options are in the table below. CONFIG_* variables are applied on every startup and always take precedence over ./config/config.json.

[!TIP] If a new image adds config options you're missing, a warning will appear in the container logs. To update, delete ./config/config.json and restart - a fresh one will be generated from the latest example, with your compose.yaml overrides re-applied.

  • Start the container: docker compose up -d

[!TIP] Monitor logs with docker logs microsoft-rewards-script, useful for viewing passwordless login codes or diagnosing issues. You can also enable a webhook in compose.yaml for notifications.


Control API and Dashboard

The optional Control API lets a local dashboard or another trusted tool monitor and control the script over HTTP. See the complete Control API documentation for setup, authentication, every endpoint, request fields, response examples, and security guidance.

Common uses include:

  • checking API health and the current run state with GET /health and GET /status;
  • reading live points, logs, errors, account summaries, run history, and error diagnostics;
  • listing safe stored-session metadata and deleting the mobile/desktop sessions for one account;
  • starting all accounts with POST /start and an empty JSON body;
  • running only one account with POST /start and {"accountIndex":2};
  • running all accounts except selected slots with POST /start and {"excludedAccountIndexes":[2,4]};
  • stopping or restarting a run with POST /stop or POST /restart;
  • streaming live logs and status updates from GET /events using Server-Sent Events (SSE);
  • reading the active configuration and schedule, with config and schedule changes available only when their explicit API_ALLOW_* options are enabled.

For example, start only ACCOUNT_2 with cURL:

curl --request POST \
  --url http://127.0.0.1:3010/start \
  --header 'Authorization: Bearer YOUR_API_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{"accountIndex":2}'

For a ready-made web interface, use the supported and endorsed Rewards Dashboard. It connects to this Control API to manage runs, accounts, schedules, logs, points, and related script settings.


Nix Setup

If using Nix: bash scripts/nix/run.sh


Configuration Options

Edit config.json to customize behavior, or set CONFIG_* environment variables in compose.yaml (Docker). Below are all currently available options.

[!WARNING] Rebuild the script (bare metal), or recreate the container (Docker) after all config changes.

Core

SettingTypeDefaultDescriptionDocker environment variable
sessionPathstring"sessions"Directory to store browser sessions
headlessbooleanfalseRun browser invisiblyAlways true in Docker
clustersnumber1Number of concurrent account clustersCONFIG_CLUSTERS
errorDiagnosticsbooleanfalseSave error and unknown-login page diagnostics under diagnostics/CONFIG_ERROR_DIAGNOSTICS
ensureStreakProtectionbooleantrueEnsure streak protection is enabledCONFIG_ENSURE_STREAK_PROTECTION
autoClaimPunchcardRewardsbooleanfalseAuto-claim completed punchcard rewardsCONFIG_AUTO_CLAIM_PUNCHCARD_REWARDS
contintueOnBotWarningbooleanfalseContinue despite the Microsoft bot-score warning (not recommended)CONFIG_CONTINTUE_ON_BOT_WARNING
skipNonPointTasksbooleantrueSkip tasks that award no pointsCONFIG_SKIP_NON_POINT_TASKS
accountDelay.minstring"1min"Minimum delay before starting the next configured accountCONFIG_ACCOUNT_DELAY_MIN
accountDelay.maxstring"3min"Maximum delay before starting the next configured accountCONFIG_ACCOUNT_DELAY_MAX
searchOnBingLocalQueriesbooleanfalseUse the local query list for ExploreOnBingCONFIG_SEARCH_ON_BING_LOCAL
globalTimeoutstring"30sec"Timeout for all actionsCONFIG_GLOBAL_TIMEOUT

Workers

SettingTypeDefaultDescriptionDocker environment variable
workers.doDailySetbooleantrueComplete daily setCONFIG_WORKER_DAILY_SET
workers.doClaimBonusPointsbooleantrueClaim bonus pointsCONFIG_WORKER_CLAIM_BONUS_POINTS
workers.doMorePromotionsbooleantrueComplete "more activities"CONFIG_WORKER_MORE_PROMOTIONS
workers.doPunchCardsbooleantrueComplete punchcardsCONFIG_WORKER_PUNCH_CARDS
workers.doAppPromotionsbooleantrueComplete app promotionsCONFIG_WORKER_APP_PROMOTIONS
workers.doDesktopSearchbooleantruePerform desktop searchesCONFIG_WORKER_DESKTOP_SEARCH
workers.doMobileSearchbooleantruePerform mobile searchesCONFIG_WORKER_MOBILE_SEARCH
workers.doBonusSearchesbooleanfalseFarm bonus searches beyond the capCONFIG_WORKER_BONUS_SEARCHES
workers.doDailyCheckInbooleantrueComplete daily check-inCONFIG_WORKER_DAILY_CHECKIN
workers.doReadToEarnbooleantrueComplete Read-to-EarnCONFIG_WORKER_READ_TO_EARN
workers.doActivateSearchPerkbooleantrueActivate the "search Nx more" perk when present (runs after the daily set)CONFIG_WORKER_ACTIVATE_SEARCH_PERK
workers.doVisualSearchbooleanfalseActivate the visual-search streak and perform visual searchesCONFIG_WORKER_VISUAL_SEARCH

Activities

SettingTypeDefaultDescriptionDocker environment variable
activities.urlRewardbooleantrueComplete URL reward activitiesCONFIG_ACTIVITY_URL_REWARD
activities.searchOnBingbooleantrueComplete ExploreOnBing offersCONFIG_ACTIVITY_SEARCH_ON_BING

Search Settings

SettingTypeDefaultDescriptionDocker environment variable
searchSettings.scrollRandomResultsbooleanfalseScroll randomly on resultsCONFIG_SEARCH_SCROLL_RANDOM
searchSettings.clickRandomResultsbooleanfalseClick random linksCONFIG_SEARCH_CLICK_RANDOM
searchSettings.runOnZeroPointsbooleanfalseRun searches even when no search points remainCONFIG_SEARCH_RUN_ON_ZERO_POINTS
searchSettings.maxBonusSearchesnumber110Max bonus searches per run (when doBonusSearches is on)CONFIG_SEARCH_MAX_BONUS_SEARCHES
searchSettings.parallelSearchingbooleantrueRun searches in parallelCONFIG_SEARCH_PARALLEL
searchSettings.clusterSearchbooleantrueCluster each main topic with Bing suggestionsCONFIG_SEARCH_CLUSTER
searchSettings.queryEnginesstring[]see Query sourcesSources used to build the search query poolCONFIG_SEARCH_QUERY_ENGINES *
searchSettings.searchResultVisitTimestring"10sec"Time to spend on each search resultCONFIG_SEARCH_VISIT_TIME
searchSettings.searchDelay.minstring"30sec"Minimum delay between searchesCONFIG_SEARCH_DELAY_MIN
searchSettings.searchDelay.maxstring"1min"Maximum delay between searchesCONFIG_SEARCH_DELAY_MAX
searchSettings.readDelay.minstring"30sec"Minimum delay for readingCONFIG_SEARCH_READ_DELAY_MIN
searchSettings.readDelay.maxstring"1min"Maximum delay for readingCONFIG_SEARCH_READ_DELAY_MAX

Desktop and mobile search quotas are tracked independently from the dashboard counters. All mobileSearch entries are combined for the mobile quota, while all pcSearch entries are combined for desktop execution; a counter explicitly identified as Edge is also shown separately for diagnostics. The script skips only the completed platform, so a completed 60/60 mobile quota does not prevent an incomplete desktop quota from running. With parallelSearching enabled, both incomplete quotas can run concurrently in their own browser contexts.

[!NOTE] * Docker CONFIG_* array values are comma-separated strings e.g. "error,warn". Regex patterns must be set directly in config.json.

Query sources

searchSettings.queryEngines controls where the main search topics come from. Pick any combination; topics from all selected sources are pooled and de-duplicated. When searchSettings.clusterSearch is enabled, each main topic is expanded on demand with Bing suggestions, that topic cluster is shuffled and completed, and only then does searching move to the next main topic.

Core sources:

SelectorSource
googleGoogle Trends (trending searches)
wikipediaWikipedia most-read articles (previous day)
wikirandomRandom Wikipedia articles
hackernewsHacker News front-page stories
redditReddit r/popular post titles
localBundled src/functions/search-queries.json list

RSS feeds use a dotted path - rss for every feed, rss.<site> for a whole site, or rss.<site>.<endpoint> for a single feed:

SelectorFeeds
rss.googleTrendsGoogle Trends RSS (gb, us)
rss.googleNewsGoogle News (gb, us, world, technology, business)
rss.bbcBBC News (top, world, technology, business, science)
rss.guardianThe Guardian (international, world, technology)
rss.theVergeThe Verge (all)
rss.arsTechnicaArs Technica (all)
rss.redditReddit listing feeds (popular, worldnews, technology)

Add your own feeds in src/constants/rssFeeds.ts.

Default:

[
    "google",
    "wikipedia",
    "wikirandom",
    "hackernews",
    "reddit",
    "local",
    "rss.googleTrends",
    "rss.googleNews",
    "rss.bbc",
    "rss.guardian.world",
    "rss.theVerge.all"
]

Experimental

Opt-in features that may change. Disabled by default.

SettingTypeDefaultDescriptionDocker environment variable
experimental.apiSearchbooleanfalsePerform Bing searches over HTTP instead of driving a browser pageCONFIG_EXPERIMENTAL_API_SEARCH
experimental.apiSearchOnBingbooleanfalseComplete ExploreOnBing offers over HTTP instead of the browserCONFIG_EXPERIMENTAL_API_SEARCH_ON_BING
experimental.blockMediabooleanfalseBlock post-login browser image and media requests to reduce trafficCONFIG_EXPERIMENTAL_BLOCK_MEDIA
experimental.edgeBrowsingbooleanfalseReport the 30-minute Edge browsing activity as a background HTTP taskCONFIG_EXPERIMENTAL_EDGE_BROWSING

When experimental.blockMedia is enabled, the automated flow activates it only after authentication has been verified and the session has been saved. The manual-login flow keeps media enabled throughout; npm run open-session still applies the configured blocker immediately because it opens an already-saved session.

When experimental.edgeBrowsing is enabled, the task starts before the normal activity sequence and runs as a separate Promise alongside Daily Set, promotions, app activities, and searches. If foreground work finishes first, the account remains open until this Promise settles. Accounts without the promotion, an access token, or remaining Edge work are skipped immediately.

Activity source layout

Standard activities live under src/functions/activities, grouped by responsibility:

  • rewards: Daily Set, More Promotions, Punch Cards, and shared promotion dispatch
  • api: individual Rewards API actions
  • app: individual mobile-app activities and App Promotions orchestration
  • search: browser search flows, search tracking, and shared SearchOnBing behavior
  • visualSearch: the visual-search activity and its browser transport
  • experimental: API Search, API SearchOnBing, Edge Browsing, and their supporting transports

Experimental activities live with the other activities under src/functions/activities/experimental. The browser-only media blocker lives at src/browser/MediaBlocker.ts. BrowserFunc contains shared Rewards/browser/session transport only, rather than individual search or visual-search implementations.

[!NOTE] Playwright documents that request routing disables the browser HTTP cache while routing is active. Image-heavy pages will usually transfer substantially less data with media blocking enabled, but cache-heavy sites are not guaranteed to use less total bandwidth or load faster. Keep this option disabled if a site depends on image/media load events.

[!NOTE] The API paths are faster but depend on the modern dashboard's endpoints. If an ExploreOnBing offer ever fails to be credited, turn apiSearchOnBing off to fall back to the browser path.

Regardless of the experimental search settings, normal Rewards actions use the cookies and action data captured during bootstrap without refreshing the visible page. The browser remains idle until a browser-backed search starts. A failed or unacknowledged URL-reward request triggers one context refresh and one retry; successful requests use the balance returned by the server action.

Logging

SettingTypeDefaultDescriptionDocker environment variable
debugLogsbooleanfalseEnable debug loggingCONFIG_DEBUG_LOGS
consoleLogFilter.enabledbooleanfalseEnable console log filteringCONFIG_LOG_FILTER_ENABLED
consoleLogFilter.modestring"whitelist"Filter mode (whitelist/blacklist)CONFIG_LOG_FILTER_MODE
consoleLogFilter.levelsstring[]["error", "warn"]Log levels to filterCONFIG_LOG_FILTER_LEVELS *
consoleLogFilter.keywordsstring[]["starting account"]Keywords to filterCONFIG_LOG_FILTER_KEYWORDS *
consoleLogFilter.regexPatternsstring[][]Regex patterns for filtering

[!NOTE] * Docker CONFIG_* array values are comma-separated strings e.g. "error,warn". Regex patterns must be set directly in config.json.

Proxy

SettingTypeDefaultDescriptionDocker environment variable
proxy.queryEnginebooleantrueProxy query engine requestsCONFIG_PROXY_QUERY_ENGINE
proxy.ignoreCertificateErrorsbooleanfalseDisable browser TLS certificate verification for intercept proxiesCONFIG_PROXY_IGNORE_CERTIFICATE_ERRORS

Leave proxy.ignoreCertificateErrors disabled for normal HTTP(S)/SOCKS proxies. Enabling it weakens TLS protection for the entire browser context and should only be used when a trusted intercepting proxy cannot otherwise present a valid certificate.

proxy.queryEngine controls whether query-source HTTP requests use the account HTTP proxy. Set the corresponding ACCOUNT_N_PROXY_HTTP=true (and configure ACCOUNT_N_PROXY_*) for those HTTP requests to have a proxy available; browser traffic uses ACCOUNT_N_PROXY_URL independently.

Account browser proxies support http://, https://, socks4://, and socks5:// (a bare hostname is treated as HTTP). HTTP(S) proxies may use ACCOUNT_N_PROXY_USERNAME and ACCOUNT_N_PROXY_PASSWORD; Patchright does not support browser authentication for SOCKS4/SOCKS5 proxies. Invalid protocols, ports, partial credentials, and authenticated SOCKS proxy configurations are rejected during account validation before the browser starts.

Webhooks

SettingTypeDefaultDescriptionDocker environment variable
webhook.discord.enabledbooleanfalseEnable Discord webhookCONFIG_DISCORD_ENABLED
webhook.discord.urlstring""Discord webhook URLCONFIG_DISCORD_URL
webhook.telegram.enabledbooleanfalseEnable Telegram webhookCONFIG_TELEGRAM_ENABLED
webhook.telegram.botTokenstring""Telegram bot tokenCONFIG_TELEGRAM_BOTTOKEN
webhook.telegram.chatIdstring""Telegram chat idCONFIG_TELEGRAM_CHATID
webhook.ntfy.enabledbooleanfalseEnable ntfy notificationsCONFIG_NTFY_ENABLED
webhook.ntfy.urlstring""ntfy server URLCONFIG_NTFY_URL
webhook.ntfy.topicstring""ntfy topicCONFIG_NTFY_TOPIC
webhook.ntfy.tokenstring""ntfy authentication tokenCONFIG_NTFY_TOKEN
webhook.ntfy.titlestring"Microsoft-Rewards-Script"Notification titleCONFIG_NTFY_TITLE
webhook.ntfy.tagsstring[]["bot", "notify"]Notification tagsCONFIG_NTFY_TAGS *
webhook.ntfy.prioritynumber3Notification priority (1-5)CONFIG_NTFY_PRIORITY
webhook.webhookLogFilter.enabledbooleanfalseEnable webhook log filteringCONFIG_WEBHOOK_LOG_FILTER_ENABLED
webhook.webhookLogFilter.modestring"whitelist"Filter mode (whitelist/blacklist)CONFIG_WEBHOOK_LOG_FILTER_MODE
webhook.webhookLogFilter.levelsstring[]["error"]Log levels to sendCONFIG_WEBHOOK_LOG_FILTER_LEVELS *
webhook.webhookLogFilter.keywordsstring[]["starting account", "select number", "collected"]Keywords to filterCONFIG_WEBHOOK_LOG_FILTER_KEYWORDS *
webhook.webhookLogFilter.regexPatternsstring[][]Regex patterns for filtering

[!NOTE] * Docker CONFIG_* array values are comma-separated strings e.g. "error,warn". Regex patterns must be set directly in config.json.

[!WARNING] NTFY users set the webhookLogFilter to enabled, or you will receive push notifications for all logs. When enabled, only account start, 2FA codes, and account completion summaries are delivered as push notifications. Customize which notifications you receive with the keywords options.


Troubleshooting

[!TIP] Most login issues can be fixed by deleting your /sessions folder, and redeploying the script

Manual login

Use the manual-login command when an account needs an interactive Microsoft sign-in. It opens the same bundled patched Chromium browser in headful mode and does not invoke the automated login handler. After you finish signing in, the command waits until the browser remains on rewards.bing.com for five continuous seconds, saves the session, and closes the browser automatically.

# Create or refresh the mobile session used at the start of automated runs
npm run manual-login -- --email [email protected]

# Create or refresh only the desktop session
npm run manual-login -- --email [email protected] --platform desktop

# Create mobile and desktop sessions sequentially
npm run manual-login -- --email [email protected] --platform both

# Ignore existing cookies and perform a clean sign-in
npm run manual-login -- --email [email protected] --fresh

The email must match an ACCOUNT_N_EMAIL entry in .env. Existing cookies are restored by default, while --fresh starts without them but retains a compatible saved fingerprint when fingerprint persistence is enabled. The command uses the selected account's language, region, proxy, proxy credentials, and fingerprint settings from .env. For consistent device identity between the manual and automated browser, enable ACCOUNT_N_SAVE_FINGERPRINT_MOBILE=true and/or ACCOUNT_N_SAVE_FINGERPRINT_DESKTOP=true for the platforms you use.

The session path, global timeout, media-blocking option, and proxy TLS option come from config.json. The corresponding CONFIG_GLOBAL_TIMEOUT, CONFIG_EXPERIMENTAL_BLOCK_MEDIA, and CONFIG_PROXY_IGNORE_CERTIFICATE_ERRORS environment overrides are also applied after .env is loaded. Manual login forces a visible browser and defers media blocking for the entire interactive authentication flow, even when experimental.blockMedia is enabled. Automated runs resume the configured blocker only after login verification and session saving, so authentication SVGs, QR codes, and videos cannot be blocked by this option.

Run this command directly on a computer with a graphical desktop and a full Patchright Chromium installation. The default Docker image contains only the headless browser shell and cannot display this interactive window.

Session management

The session utility requires an explicit command, so running it without an argument only displays help and never deletes anything.

# List stored mobile and desktop sessions
npm run clear-sessions -- list

# Delete the sessions belonging to one account
npm run clear-sessions -- email [email protected]

# Delete every stored session
npm run clear-sessions -- all
# List safe session metadata
curl --request GET \
  --url http://127.0.0.1:3010/sessions \
  --header 'Authorization: Bearer YOUR_API_TOKEN'

# Delete only [email protected]'s mobile and desktop sessions
curl --request DELETE \
  --url http://127.0.0.1:3010/sessions/user%40example.com \
  --header 'Authorization: Bearer YOUR_API_TOKEN'

See the Control API session documentation for response data, Axios examples, and error behavior.


Disclaimer

Use at your own risk.
Automation of Microsoft Rewards may lead to account suspension or bans.
This software is provided for educational purposes only.
The authors are not responsible for any actions taken by Microsoft.

bot
docker
microsoft-rewards
microsoft-rewards-bot
microsoft-rewards-farmer
microsoft-rewards-script
playwright
script
typescript

TheNetsky/Microsoft-Rewards-Script

Automated Microsoft Rewards script, using TypeScript and Playwright.

TypeScript

1,107

260 commits

updated Oct 12, 2026

See the code

README

Discord Latest Build Docker

[!TIP] This version supports the new, modern Bing Rewards dashboard only - it does not support the legacy dashboard. If your account still uses the old dashboard, use the v3 branch and v3.x releases instead!

Use at your own risk - some features may not work as expected.


Table of Contents


Quick Setup

Bare metal

Requirements: Node.js >= 24 and Git
Works on Windows, Linux, macOS, and WSL.

Get the script

git clone https://github.com/TheNetsky/Microsoft-Rewards-Script.git
cd Microsoft-Rewards-Script

Or, download the latest release ZIP and extract it.

Account Setup

  • Copy and rename env.example to .env and add your account credentials:
[email protected]
# ACCOUNT_1_PASSWORD=your_password

[!NOTE] ACCOUNT_N_PASSWORD is optional. Set it when password sign-in should be available; leave it unset for passwordless/Authenticator-only accounts.

Add one ACCOUNT_N_* block per account. Account slots do not need to be contiguous: ACCOUNT_2 or ACCOUNT_4 can be configured even when earlier slots are missing. Accounts run in ascending slot order. Optional per-account fields cover recovery email, locale, language, proxy, and fingerprint persistence - see env.example for all of them.

ACCOUNT_N_LANG_CODE accepts a BCP 47 language tag such as nl, it, or pt-BR. ACCOUNT_N_GEO_LOCALE accepts a two-letter country code or defaults to auto. The selected language and country are applied consistently to browser fingerprints, Accept-Language, Microsoft Rewards app headers, and market-specific requests. In auto mode, the country reported by the Microsoft profile is cached after the first successful dashboard request; changing either locale setting automatically replaces an incompatible saved fingerprint.

[!TIP] For 2FA accounts, set ACCOUNT_N_TOTP_SECRET and the script will generate and enter the 6-digit code automatically. To get the secret: in your Microsoft Security settings open 'Manage how you sign in', add an Authenticator app, and when the QR code appears choose 'enter code manually' - use that code as the value in your .env.

[!WARNING] You must rebuild your script after making any changes to the .env.

Config Setup

[!WARNING] Do not skip this step if you are running the script bare metal.

  • Bare metal: Copy or rename config.example.json to config.json (in the project root) and customize your preferences.
  • Docker: A valid config.json is automatically created on first run and saved locally to ./config/. You can optionally manually create a config.json (e.g., if you need to specify regex values) using the provided config.example.json

[!CAUTION] Prior versions of accounts.json and config.json are not compatible with current release.

Build and run the script (bare metal version)

npm run pre-build
npm run build
npm run start

Docker

[email protected]
# ACCOUNT_1_PASSWORD=your_password

ACCOUNT_N_PASSWORD is optional; omit it for passwordless/Authenticator-only accounts.

  • Review compose.yaml to adjust scheduling, timezone, and config options.

[!NOTE] A valid config.json is auto-generated on first run using default values, and saved locally to ./config/. Optionally, use CONFIG_* variables in the environment: section of the compose.yaml to customise your options (e.g., clusters, webhook, etc.). A full list of available options are in the table below. CONFIG_* variables are applied on every startup and always take precedence over ./config/config.json.

[!TIP] If a new image adds config options you're missing, a warning will appear in the container logs. To update, delete ./config/config.json and restart - a fresh one will be generated from the latest example, with your compose.yaml overrides re-applied.

  • Start the container: docker compose up -d

[!TIP] Monitor logs with docker logs microsoft-rewards-script, useful for viewing passwordless login codes or diagnosing issues. You can also enable a webhook in compose.yaml for notifications.


Control API and Dashboard

The optional Control API lets a local dashboard or another trusted tool monitor and control the script over HTTP. See the complete Control API documentation for setup, authentication, every endpoint, request fields, response examples, and security guidance.

Common uses include:

  • checking API health and the current run state with GET /health and GET /status;
  • reading live points, logs, errors, account summaries, run history, and error diagnostics;
  • listing safe stored-session metadata and deleting the mobile/desktop sessions for one account;
  • starting all accounts with POST /start and an empty JSON body;
  • running only one account with POST /start and {"accountIndex":2};
  • running all accounts except selected slots with POST /start and {"excludedAccountIndexes":[2,4]};
  • stopping or restarting a run with POST /stop or POST /restart;
  • streaming live logs and status updates from GET /events using Server-Sent Events (SSE);
  • reading the active configuration and schedule, with config and schedule changes available only when their explicit API_ALLOW_* options are enabled.

For example, start only ACCOUNT_2 with cURL:

curl --request POST \
  --url http://127.0.0.1:3010/start \
  --header 'Authorization: Bearer YOUR_API_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{"accountIndex":2}'

For a ready-made web interface, use the supported and endorsed Rewards Dashboard. It connects to this Control API to manage runs, accounts, schedules, logs, points, and related script settings.


Nix Setup

If using Nix: bash scripts/nix/run.sh


Configuration Options

Edit config.json to customize behavior, or set CONFIG_* environment variables in compose.yaml (Docker). Below are all currently available options.

[!WARNING] Rebuild the script (bare metal), or recreate the container (Docker) after all config changes.

Core

SettingTypeDefaultDescriptionDocker environment variable
sessionPathstring"sessions"Directory to store browser sessions
headlessbooleanfalseRun browser invisiblyAlways true in Docker
clustersnumber1Number of concurrent account clustersCONFIG_CLUSTERS
errorDiagnosticsbooleanfalseSave error and unknown-login page diagnostics under diagnostics/CONFIG_ERROR_DIAGNOSTICS
ensureStreakProtectionbooleantrueEnsure streak protection is enabledCONFIG_ENSURE_STREAK_PROTECTION
autoClaimPunchcardRewardsbooleanfalseAuto-claim completed punchcard rewardsCONFIG_AUTO_CLAIM_PUNCHCARD_REWARDS
contintueOnBotWarningbooleanfalseContinue despite the Microsoft bot-score warning (not recommended)CONFIG_CONTINTUE_ON_BOT_WARNING
skipNonPointTasksbooleantrueSkip tasks that award no pointsCONFIG_SKIP_NON_POINT_TASKS
accountDelay.minstring"1min"Minimum delay before starting the next configured accountCONFIG_ACCOUNT_DELAY_MIN
accountDelay.maxstring"3min"Maximum delay before starting the next configured accountCONFIG_ACCOUNT_DELAY_MAX
searchOnBingLocalQueriesbooleanfalseUse the local query list for ExploreOnBingCONFIG_SEARCH_ON_BING_LOCAL
globalTimeoutstring"30sec"Timeout for all actionsCONFIG_GLOBAL_TIMEOUT

Workers

SettingTypeDefaultDescriptionDocker environment variable
workers.doDailySetbooleantrueComplete daily setCONFIG_WORKER_DAILY_SET
workers.doClaimBonusPointsbooleantrueClaim bonus pointsCONFIG_WORKER_CLAIM_BONUS_POINTS
workers.doMorePromotionsbooleantrueComplete "more activities"CONFIG_WORKER_MORE_PROMOTIONS
workers.doPunchCardsbooleantrueComplete punchcardsCONFIG_WORKER_PUNCH_CARDS
workers.doAppPromotionsbooleantrueComplete app promotionsCONFIG_WORKER_APP_PROMOTIONS
workers.doDesktopSearchbooleantruePerform desktop searchesCONFIG_WORKER_DESKTOP_SEARCH
workers.doMobileSearchbooleantruePerform mobile searchesCONFIG_WORKER_MOBILE_SEARCH
workers.doBonusSearchesbooleanfalseFarm bonus searches beyond the capCONFIG_WORKER_BONUS_SEARCHES
workers.doDailyCheckInbooleantrueComplete daily check-inCONFIG_WORKER_DAILY_CHECKIN
workers.doReadToEarnbooleantrueComplete Read-to-EarnCONFIG_WORKER_READ_TO_EARN
workers.doActivateSearchPerkbooleantrueActivate the "search Nx more" perk when present (runs after the daily set)CONFIG_WORKER_ACTIVATE_SEARCH_PERK
workers.doVisualSearchbooleanfalseActivate the visual-search streak and perform visual searchesCONFIG_WORKER_VISUAL_SEARCH

Activities

SettingTypeDefaultDescriptionDocker environment variable
activities.urlRewardbooleantrueComplete URL reward activitiesCONFIG_ACTIVITY_URL_REWARD
activities.searchOnBingbooleantrueComplete ExploreOnBing offersCONFIG_ACTIVITY_SEARCH_ON_BING

Search Settings

SettingTypeDefaultDescriptionDocker environment variable
searchSettings.scrollRandomResultsbooleanfalseScroll randomly on resultsCONFIG_SEARCH_SCROLL_RANDOM
searchSettings.clickRandomResultsbooleanfalseClick random linksCONFIG_SEARCH_CLICK_RANDOM
searchSettings.runOnZeroPointsbooleanfalseRun searches even when no search points remainCONFIG_SEARCH_RUN_ON_ZERO_POINTS
searchSettings.maxBonusSearchesnumber110Max bonus searches per run (when doBonusSearches is on)CONFIG_SEARCH_MAX_BONUS_SEARCHES
searchSettings.parallelSearchingbooleantrueRun searches in parallelCONFIG_SEARCH_PARALLEL
searchSettings.clusterSearchbooleantrueCluster each main topic with Bing suggestionsCONFIG_SEARCH_CLUSTER
searchSettings.queryEnginesstring[]see Query sourcesSources used to build the search query poolCONFIG_SEARCH_QUERY_ENGINES *
searchSettings.searchResultVisitTimestring"10sec"Time to spend on each search resultCONFIG_SEARCH_VISIT_TIME
searchSettings.searchDelay.minstring"30sec"Minimum delay between searchesCONFIG_SEARCH_DELAY_MIN
searchSettings.searchDelay.maxstring"1min"Maximum delay between searchesCONFIG_SEARCH_DELAY_MAX
searchSettings.readDelay.minstring"30sec"Minimum delay for readingCONFIG_SEARCH_READ_DELAY_MIN
searchSettings.readDelay.maxstring"1min"Maximum delay for readingCONFIG_SEARCH_READ_DELAY_MAX

Desktop and mobile search quotas are tracked independently from the dashboard counters. All mobileSearch entries are combined for the mobile quota, while all pcSearch entries are combined for desktop execution; a counter explicitly identified as Edge is also shown separately for diagnostics. The script skips only the completed platform, so a completed 60/60 mobile quota does not prevent an incomplete desktop quota from running. With parallelSearching enabled, both incomplete quotas can run concurrently in their own browser contexts.

[!NOTE] * Docker CONFIG_* array values are comma-separated strings e.g. "error,warn". Regex patterns must be set directly in config.json.

Query sources

searchSettings.queryEngines controls where the main search topics come from. Pick any combination; topics from all selected sources are pooled and de-duplicated. When searchSettings.clusterSearch is enabled, each main topic is expanded on demand with Bing suggestions, that topic cluster is shuffled and completed, and only then does searching move to the next main topic.

Core sources:

SelectorSource
googleGoogle Trends (trending searches)
wikipediaWikipedia most-read articles (previous day)
wikirandomRandom Wikipedia articles
hackernewsHacker News front-page stories
redditReddit r/popular post titles
localBundled src/functions/search-queries.json list

RSS feeds use a dotted path - rss for every feed, rss.<site> for a whole site, or rss.<site>.<endpoint> for a single feed:

SelectorFeeds
rss.googleTrendsGoogle Trends RSS (gb, us)
rss.googleNewsGoogle News (gb, us, world, technology, business)
rss.bbcBBC News (top, world, technology, business, science)
rss.guardianThe Guardian (international, world, technology)
rss.theVergeThe Verge (all)
rss.arsTechnicaArs Technica (all)
rss.redditReddit listing feeds (popular, worldnews, technology)

Add your own feeds in src/constants/rssFeeds.ts.

Default:

[
    "google",
    "wikipedia",
    "wikirandom",
    "hackernews",
    "reddit",
    "local",
    "rss.googleTrends",
    "rss.googleNews",
    "rss.bbc",
    "rss.guardian.world",
    "rss.theVerge.all"
]

Experimental

Opt-in features that may change. Disabled by default.

SettingTypeDefaultDescriptionDocker environment variable
experimental.apiSearchbooleanfalsePerform Bing searches over HTTP instead of driving a browser pageCONFIG_EXPERIMENTAL_API_SEARCH
experimental.apiSearchOnBingbooleanfalseComplete ExploreOnBing offers over HTTP instead of the browserCONFIG_EXPERIMENTAL_API_SEARCH_ON_BING
experimental.blockMediabooleanfalseBlock post-login browser image and media requests to reduce trafficCONFIG_EXPERIMENTAL_BLOCK_MEDIA
experimental.edgeBrowsingbooleanfalseReport the 30-minute Edge browsing activity as a background HTTP taskCONFIG_EXPERIMENTAL_EDGE_BROWSING

When experimental.blockMedia is enabled, the automated flow activates it only after authentication has been verified and the session has been saved. The manual-login flow keeps media enabled throughout; npm run open-session still applies the configured blocker immediately because it opens an already-saved session.

When experimental.edgeBrowsing is enabled, the task starts before the normal activity sequence and runs as a separate Promise alongside Daily Set, promotions, app activities, and searches. If foreground work finishes first, the account remains open until this Promise settles. Accounts without the promotion, an access token, or remaining Edge work are skipped immediately.

Activity source layout

Standard activities live under src/functions/activities, grouped by responsibility:

  • rewards: Daily Set, More Promotions, Punch Cards, and shared promotion dispatch
  • api: individual Rewards API actions
  • app: individual mobile-app activities and App Promotions orchestration
  • search: browser search flows, search tracking, and shared SearchOnBing behavior
  • visualSearch: the visual-search activity and its browser transport
  • experimental: API Search, API SearchOnBing, Edge Browsing, and their supporting transports

Experimental activities live with the other activities under src/functions/activities/experimental. The browser-only media blocker lives at src/browser/MediaBlocker.ts. BrowserFunc contains shared Rewards/browser/session transport only, rather than individual search or visual-search implementations.

[!NOTE] Playwright documents that request routing disables the browser HTTP cache while routing is active. Image-heavy pages will usually transfer substantially less data with media blocking enabled, but cache-heavy sites are not guaranteed to use less total bandwidth or load faster. Keep this option disabled if a site depends on image/media load events.

[!NOTE] The API paths are faster but depend on the modern dashboard's endpoints. If an ExploreOnBing offer ever fails to be credited, turn apiSearchOnBing off to fall back to the browser path.

Regardless of the experimental search settings, normal Rewards actions use the cookies and action data captured during bootstrap without refreshing the visible page. The browser remains idle until a browser-backed search starts. A failed or unacknowledged URL-reward request triggers one context refresh and one retry; successful requests use the balance returned by the server action.

Logging

SettingTypeDefaultDescriptionDocker environment variable
debugLogsbooleanfalseEnable debug loggingCONFIG_DEBUG_LOGS
consoleLogFilter.enabledbooleanfalseEnable console log filteringCONFIG_LOG_FILTER_ENABLED
consoleLogFilter.modestring"whitelist"Filter mode (whitelist/blacklist)CONFIG_LOG_FILTER_MODE
consoleLogFilter.levelsstring[]["error", "warn"]Log levels to filterCONFIG_LOG_FILTER_LEVELS *
consoleLogFilter.keywordsstring[]["starting account"]Keywords to filterCONFIG_LOG_FILTER_KEYWORDS *
consoleLogFilter.regexPatternsstring[][]Regex patterns for filtering

[!NOTE] * Docker CONFIG_* array values are comma-separated strings e.g. "error,warn". Regex patterns must be set directly in config.json.

Proxy

SettingTypeDefaultDescriptionDocker environment variable
proxy.queryEnginebooleantrueProxy query engine requestsCONFIG_PROXY_QUERY_ENGINE
proxy.ignoreCertificateErrorsbooleanfalseDisable browser TLS certificate verification for intercept proxiesCONFIG_PROXY_IGNORE_CERTIFICATE_ERRORS

Leave proxy.ignoreCertificateErrors disabled for normal HTTP(S)/SOCKS proxies. Enabling it weakens TLS protection for the entire browser context and should only be used when a trusted intercepting proxy cannot otherwise present a valid certificate.

proxy.queryEngine controls whether query-source HTTP requests use the account HTTP proxy. Set the corresponding ACCOUNT_N_PROXY_HTTP=true (and configure ACCOUNT_N_PROXY_*) for those HTTP requests to have a proxy available; browser traffic uses ACCOUNT_N_PROXY_URL independently.

Account browser proxies support http://, https://, socks4://, and socks5:// (a bare hostname is treated as HTTP). HTTP(S) proxies may use ACCOUNT_N_PROXY_USERNAME and ACCOUNT_N_PROXY_PASSWORD; Patchright does not support browser authentication for SOCKS4/SOCKS5 proxies. Invalid protocols, ports, partial credentials, and authenticated SOCKS proxy configurations are rejected during account validation before the browser starts.

Webhooks

SettingTypeDefaultDescriptionDocker environment variable
webhook.discord.enabledbooleanfalseEnable Discord webhookCONFIG_DISCORD_ENABLED
webhook.discord.urlstring""Discord webhook URLCONFIG_DISCORD_URL
webhook.telegram.enabledbooleanfalseEnable Telegram webhookCONFIG_TELEGRAM_ENABLED
webhook.telegram.botTokenstring""Telegram bot tokenCONFIG_TELEGRAM_BOTTOKEN
webhook.telegram.chatIdstring""Telegram chat idCONFIG_TELEGRAM_CHATID
webhook.ntfy.enabledbooleanfalseEnable ntfy notificationsCONFIG_NTFY_ENABLED
webhook.ntfy.urlstring""ntfy server URLCONFIG_NTFY_URL
webhook.ntfy.topicstring""ntfy topicCONFIG_NTFY_TOPIC
webhook.ntfy.tokenstring""ntfy authentication tokenCONFIG_NTFY_TOKEN
webhook.ntfy.titlestring"Microsoft-Rewards-Script"Notification titleCONFIG_NTFY_TITLE
webhook.ntfy.tagsstring[]["bot", "notify"]Notification tagsCONFIG_NTFY_TAGS *
webhook.ntfy.prioritynumber3Notification priority (1-5)CONFIG_NTFY_PRIORITY
webhook.webhookLogFilter.enabledbooleanfalseEnable webhook log filteringCONFIG_WEBHOOK_LOG_FILTER_ENABLED
webhook.webhookLogFilter.modestring"whitelist"Filter mode (whitelist/blacklist)CONFIG_WEBHOOK_LOG_FILTER_MODE
webhook.webhookLogFilter.levelsstring[]["error"]Log levels to sendCONFIG_WEBHOOK_LOG_FILTER_LEVELS *
webhook.webhookLogFilter.keywordsstring[]["starting account", "select number", "collected"]Keywords to filterCONFIG_WEBHOOK_LOG_FILTER_KEYWORDS *
webhook.webhookLogFilter.regexPatternsstring[][]Regex patterns for filtering

[!NOTE] * Docker CONFIG_* array values are comma-separated strings e.g. "error,warn". Regex patterns must be set directly in config.json.

[!WARNING] NTFY users set the webhookLogFilter to enabled, or you will receive push notifications for all logs. When enabled, only account start, 2FA codes, and account completion summaries are delivered as push notifications. Customize which notifications you receive with the keywords options.


Troubleshooting

[!TIP] Most login issues can be fixed by deleting your /sessions folder, and redeploying the script

Manual login

Use the manual-login command when an account needs an interactive Microsoft sign-in. It opens the same bundled patched Chromium browser in headful mode and does not invoke the automated login handler. After you finish signing in, the command waits until the browser remains on rewards.bing.com for five continuous seconds, saves the session, and closes the browser automatically.

# Create or refresh the mobile session used at the start of automated runs
npm run manual-login -- --email [email protected]

# Create or refresh only the desktop session
npm run manual-login -- --email [email protected] --platform desktop

# Create mobile and desktop sessions sequentially
npm run manual-login -- --email [email protected] --platform both

# Ignore existing cookies and perform a clean sign-in
npm run manual-login -- --email [email protected] --fresh

The email must match an ACCOUNT_N_EMAIL entry in .env. Existing cookies are restored by default, while --fresh starts without them but retains a compatible saved fingerprint when fingerprint persistence is enabled. The command uses the selected account's language, region, proxy, proxy credentials, and fingerprint settings from .env. For consistent device identity between the manual and automated browser, enable ACCOUNT_N_SAVE_FINGERPRINT_MOBILE=true and/or ACCOUNT_N_SAVE_FINGERPRINT_DESKTOP=true for the platforms you use.

The session path, global timeout, media-blocking option, and proxy TLS option come from config.json. The corresponding CONFIG_GLOBAL_TIMEOUT, CONFIG_EXPERIMENTAL_BLOCK_MEDIA, and CONFIG_PROXY_IGNORE_CERTIFICATE_ERRORS environment overrides are also applied after .env is loaded. Manual login forces a visible browser and defers media blocking for the entire interactive authentication flow, even when experimental.blockMedia is enabled. Automated runs resume the configured blocker only after login verification and session saving, so authentication SVGs, QR codes, and videos cannot be blocked by this option.

Run this command directly on a computer with a graphical desktop and a full Patchright Chromium installation. The default Docker image contains only the headless browser shell and cannot display this interactive window.

Session management

The session utility requires an explicit command, so running it without an argument only displays help and never deletes anything.

# List stored mobile and desktop sessions
npm run clear-sessions -- list

# Delete the sessions belonging to one account
npm run clear-sessions -- email [email protected]

# Delete every stored session
npm run clear-sessions -- all
# List safe session metadata
curl --request GET \
  --url http://127.0.0.1:3010/sessions \
  --header 'Authorization: Bearer YOUR_API_TOKEN'

# Delete only [email protected]'s mobile and desktop sessions
curl --request DELETE \
  --url http://127.0.0.1:3010/sessions/user%40example.com \
  --header 'Authorization: Bearer YOUR_API_TOKEN'

See the Control API session documentation for response data, Axios examples, and error behavior.


Disclaimer

Use at your own risk.
Automation of Microsoft Rewards may lead to account suspension or bans.
This software is provided for educational purposes only.
The authors are not responsible for any actions taken by Microsoft.

bot
docker
microsoft-rewards
microsoft-rewards-bot
microsoft-rewards-farmer
microsoft-rewards-script
playwright
script
typescript

Significant stargazers

JohnsonRan

117 followers · starred Jul 2026

Jorge Montejo

16 followers · starred Jul 2026

100

18 followers · starred Jan 2026

raystorm

16 followers · starred Oct 2026