Using Singapore mobile proxies with playwright-stealth in 2026
Using Singapore mobile proxies with playwright-stealth in 2026
If you’ve been running playwright-stealth for a while, there’s a specific moment that sends you looking for mobile proxies: your scripts pass the headless detection checks, your fingerprints look clean, but you’re still getting soft-blocked, served empty results, or silently rate-limited within a few requests. The automation is technically stealthy. The IP isn’t. By 2026, most platforms that matter in Southeast Asia have moved well past UA sniffing and canvas fingerprinting. They’re scoring IP reputation, ASN type, and carrier metadata before your first DOM interaction even completes. That’s where mobile proxies fill the gap.
why playwright-stealth hits walls without datacenter or VPN IPs
playwright-stealth does an excellent job of patching the browser’s self-reporting surface: navigator properties, WebGL renderer strings, the permissions API quirks that headless Chromium exposes by default. What it can’t patch is the network-layer metadata that platforms read before serving the first byte. A datacenter IP from AWS ap-southeast-1 carries an ASN that every major threat-intelligence feed has flagged as automation infrastructure. A VPN endpoint is marginally better, but VPN ranges get burned fast, especially in high-volume scraping contexts. The request hits the CDN edge, the ASN lookup returns “Choopa LLC” or “M247 Ltd”, and the scoring model adjusts before your page.goto() promise resolves.
The problem compounds with tools like playwright-stealth because they’re specifically designed for workflows that need to look human. Price monitoring on Lazada or Shopee, competitor research on local classified platforms, form submission testing on government portals: these are workflows where the operator has already invested in fingerprint hygiene. The irony is that better fingerprint hygiene can actually increase scrutiny on the IP. A perfectly clean browser fingerprint arriving from a datacenter ASN looks more anomalous than a slightly rough fingerprint from a residential mobile IP, because real humans on mobile browsers have rough edges.
Rotating through a pool of residential IPs helps, but the category matters. US and EU residential pools are widely available and widely abused. Many Southeast Asian platforms specifically track the geographic and carrier origin of traffic, not just because they want to serve local content, but because their fraud models are tuned to expect that legitimate local users arrive from local carriers. A Singapore-based e-commerce site or financial comparison platform sees the overwhelming majority of its organic traffic from SingTel, StarHub, M1, and MVNO networks. Traffic that looks behaviorally local but arrives from a US residential pool stands out in the aggregates, even if no individual request triggers a rule. If you want to understand the broader category before wiring it up, what is a mobile proxy covers the infrastructure differences in detail.
setting up SMP credentials in playwright-stealth
Singapore Mobile Proxy (SMP) provides HTTP and SOCKS5 endpoints backed by real modems on SingTel, StarHub, M1, and Vivifi. The credential format follows the standard ip:port:username:password pattern. You get a host, a port, and per-account credentials. The setup in playwright-stealth is straightforward because Playwright’s proxy config accepts these directly at the browser or context level.
Here’s a complete setup that applies the proxy at the browser context level, which is the right scope for most automation workflows. Applying it at the browser level works too, but context-level lets you run multiple contexts with different proxy configs in the same browser instance if you need it.
import { chromium } from 'playwright';
import { stealth } from 'playwright-stealth';
const SMP_HOST = 'your.smp.host';
const SMP_PORT = 10000; // your assigned port
const SMP_USER = 'your_username';
const SMP_PASS = 'your_password';
(async () => {
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({
proxy: {
server: `http://${SMP_HOST}:${SMP_PORT}`,
username: SMP_USER,
password: SMP_PASS,
},
// match a realistic Singapore mobile viewport
viewport: { width: 390, height: 844 },
userAgent:
'Mozilla/5.0 (iPhone; CPU iPhone OS 17_4 like Mac OS X) ' +
'AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1',
locale: 'en-SG',
timezoneId: 'Asia/Singapore',
});
await stealth(context);
const page = await context.newPage();
await page.goto('https://example.com');
// your automation here
await browser.close();
})();
The userAgent here is a mobile Safari string because you’re routing through a mobile carrier IP. A desktop Chrome UA arriving from a SingTel IP is an unusual combination that some platforms score negatively. The locale and timezoneId settings reinforce the Singapore signal at the JavaScript layer, which playwright-stealth exposes via Intl API patches. Leave these at their defaults (typically UTC and en-US) and you create a detectable mismatch between the IP geolocation and the browser’s self-reported locale. That mismatch is exactly the kind of signal that 2026-era bot scoring systems are trained to catch.
SOCKS5 is also available if your workflow requires it. The server string becomes socks5://${SMP_HOST}:${SMP_PORT}. Playwright supports SOCKS5 proxies natively. The choice between HTTP and SOCKS5 for this use case is mostly about what your network environment allows; the HTTP vs SOCKS5 mobile proxies breakdown covers the tradeoffs in depth if you’re unsure which to reach for.
rotating IPs per request or per session
SMP offers two endpoint modes: rotating and sticky. Understanding when to use each matters more than most proxy documentation admits.
Sticky sessions give you the same exit IP for the duration of a session window (typically 10 to 30 minutes depending on your plan). Use sticky when your workflow involves state: login flows, multi-step forms, checkout sequences, anything where the platform is tracking a session token and may bind it to an IP. Changing IPs mid-session on these workflows will get your session invalidated or trigger step-up authentication. It’s also the right mode for any task where you need consistent geolocation across a sequence of requests, since some platforms embed the originating IP into signed tokens.
Rotating mode assigns a fresh IP on each request or each new connection, depending on how the endpoint is configured. Use rotating for stateless scraping: public search results, product listings, pricing data, anything where you’re not logged in and each request is independent. The tradeoff is that you burn through more of the carrier IP pool, but you get much stronger resistance to per-IP rate limits.
Here’s a pattern for rotating contexts in playwright-stealth, creating a fresh browser context (and therefore a fresh proxy connection) for each logical unit of work:
import { chromium, BrowserContext } from 'playwright';
import { stealth } from 'playwright-stealth';
const PROXY_CONFIG = {
server: `http://your.smp.host:10000`,
username: 'your_username',
password: 'your_password',
};
async function scrapeWithRotation(urls: string[]): Promise<string[]> {
const browser = await chromium.launch({ headless: true });
const results: string[] = [];
for (const url of urls) {
// new context per URL = new TCP connection = rotation endpoint picks new IP
const context: BrowserContext = await browser.newContext({
proxy: PROXY_CONFIG,
viewport: { width: 390, height: 844 },
userAgent:
'Mozilla/5.0 (Linux; Android 14; Pixel 8) ' +
'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Mobile Safari/537.36',
locale: 'en-SG',
timezoneId: 'Asia/Singapore',
});
await stealth(context);
const page = await context.newPage();
try {
await page.goto(url, { waitUntil: 'domcontentloaded' });
const content = await page.content();
results.push(content);
} finally {
await context.close(); // close context, releasing the connection
}
}
await browser.close();
return results;
}
The key mechanic here is that closing and reopening the browser context forces a new TCP connection through the proxy, which triggers IP rotation on the SMP rotating endpoint. If you reuse the same context across requests, many proxy providers will keep the same exit IP for connection persistence reasons, even on a “rotating” endpoint. When you need guaranteed rotation, close the context between logical units of work.
For workflows that are neither fully stateless nor fully stateful, sticky sessions with a moderate window (10 minutes) are usually the right default. You get enough IP consistency to complete multi-step sequences without committing to the same IP indefinitely.
three real workflows where this combo wins
price monitoring on local e-commerce platforms
Platforms like Shopee and Lazada have sophisticated anti-scraping infrastructure that correlates IP reputation, request cadence, and fingerprint signals. playwright-stealth handles the fingerprint layer well. The gap, in practice, is that these platforms have seen enough US and EU residential proxies used for scraping that they’ve built dedicated models for identifying them. Traffic from a SingTel or StarHub IP is treated as organic Singapore shopper traffic by default, which means the scoring thresholds are calibrated against real user behavior rather than against known proxy ranges. A well-configured playwright-stealth session on an SMP mobile IP can sustain realistic request cadences without triggering soft blocks, while the same session on a datacenter or foreign residential IP gets rate-limited within minutes. The competitive research use case described in mobile proxies for SEO research overlaps with this workflow heavily.
testing geo-fenced content and localized UX
If you’re building or QA-testing a product that serves different content to Singapore users, playwright-stealth on SMP gives you the most accurate possible simulation of what a real Singapore mobile user sees. This isn’t just about IP-based geo-restriction. CDNs, A/B testing frameworks, and ad serving platforms all make decisions based on the combination of IP, carrier, and browser locale. A developer testing from their office in Berlin using a VPN endpoint that exits in Singapore is testing an approximation. The IP resolves to Singapore, but the ASN is a VPN provider and the carrier metadata is absent. Real carrier IPs from SMP pass the full carrier lookup, which matters for workflows that involve carrier billing integrations, telco-specific features, or any platform that has learned to distinguish real SG mobile traffic from VPN-tunneled traffic.
automated form submission and account workflows on local platforms
Government portals, financial comparison sites, and local services in Singapore often use third-party fraud detection that scores submissions based on IP origin and device signals. playwright-stealth patches the device signal layer. SMP provides the IP layer. Together, they let you run automated account creation, form submission testing, or onboarding flow QA in a way that passes the composite score. This is particularly relevant for developers working on fintech or insurtech products who need to test their own platforms under realistic conditions, or for operators running legitimate account management automation. Operating within ethical and terms-of-service boundaries matters here; ethical mobile proxy use is worth reading if you’re defining scope for your automation program.
common pitfalls
user-agent and IP type mismatch. this is the most common one. routing through a mobile carrier IP while sending a desktop Chrome UA is a detectable signal. mobile carrier IPs are expected to carry mobile UAs. set your UA to a realistic Android Chrome or mobile Safari string and match your viewport accordingly.
not closing contexts between rotations. if you’re on a rotating endpoint but reusing the same browser context, you may not be getting new IPs. proxy rotation is triggered by new connections. close and reopen contexts, or at minimum use page.close() and context.close() between work units.
geolocation API leaking the wrong coordinates. playwright-stealth patches many fingerprint vectors, but navigator.geolocation may return default or null values unless you explicitly set it. for Singapore workflows, set geolocation: { latitude: 1.3521, longitude: 103.8198 } in your context options and grant the geolocation permission. a SG carrier IP with a null geolocation response is a minor inconsistency, but it’s the kind of thing that sophisticated scoring systems accumulate into a risk score.
ignoring proxy authentication errors silently. Playwright won’t always surface proxy auth failures as obvious exceptions. if your requests are returning empty or you’re seeing unexpected redirects, add explicit logging around page.on('response', ...) to check for 407 status codes from the proxy. credential format errors are a common source of silent failures during initial setup.
session cookie invalidation on sticky session expiry. if your sticky session window expires mid-workflow, the IP changes and any session cookies that the target platform bound to your original IP will be invalidated. either size your sticky session window to comfortably cover your full workflow, or design your session management to re-authenticate when the IP changes.
skipping the timezoneId and locale settings. these are quick wins that most people skip. a browser reporting en-US and UTC while arriving from a SingTel IP looks wrong. two lines of config closes this gap.
when Singapore IPs specifically matter
The SEA internet is not a monolith, and Singapore’s infrastructure sits at a distinct position within it. Singapore is a regional hub for financial services, e-commerce, and SaaS companies serving the broader SEA market. Many platforms that operate across Thailand, Indonesia, Malaysia, and the Philippines host their primary infrastructure in Singapore and segment their content, pricing, and features by the specific country of origin. A generic “Southeast Asia residential IP” may be Malaysian or Indonesian, which gives you regional presence but not Singapore-specific content. If your workflow targets Singapore-specific pricing on travel platforms, Singapore-specific search results on Google (.com.sg), or features that are gated to Singapore residents (certain financial products, telco-specific content, or government-adjacent services), you need an IP that resolves to Singapore and carries SingTel, StarHub, or M1 carrier metadata, not just an IP in the region.
Beyond content geo-fencing, Singapore has a meaningfully different mobile carrier landscape than its neighbors. The carriers are well-known, their IP ranges are relatively stable, and platforms have strong priors about what legitimate traffic from those carriers looks like. This cuts both ways: it means your traffic blends in better when it’s genuinely coming from a SingTel or StarHub modem, and it means synthetic traffic that claims to be from Singapore but doesn’t have the right carrier fingerprint stands out more than it would with a less-scrutinized carrier network. SMP’s infrastructure uses real modems on real SG carrier SIMs, which means the ASN lookup, the PTR record, and the carrier metadata all resolve correctly. That’s the part that VPN exits and datacenter proxies claiming to be “Singapore IPs” consistently fail.
getting started
SMP’s plans page has current pricing and endpoint options across the SingTel, StarHub, M1, and Vivifi carrier pools. The credential format is consistent across plans, so the code in this post works without modification once you have your host, port, and credentials. If you’re coming from a datacenter proxy setup, the per-GB or per-connection pricing model is different from what you’re used to, but the reduction in block rates and retry overhead typically offsets the cost difference for workflows that actually need real carrier IPs. Start with a small plan, run it against your target platform, and compare the block rate against your current setup before committing to higher volume.