If you’re using PostHog to track user behavior and product analytics, it’s essential to filter out internal team members and test accounts to keep your data accurate. In this guide, you’ll learn how to set up PostHog internal user filtering to ensure clean and reliable analytics.
Why You Should Filter Internal Users in PostHog
By default, PostHog captures all events; including those from developers, marketers, QA testers, and anyone on your team. This can skew data and lead to misleading insights. Setting up filters for internal and test users in PostHog helps:
- Keep your conversion rates accurate
- Ensure event data reflects real user behavior
- Avoid false signals in A/B testing
Here’s how to exclude internal users from tracking in PostHog:
1. Go to Settings
From the PostHog sidebar, navigate to Settings. Scroll down to find the section called “Filter out internal and test users.”

2. Add Filtering Rules
You can filter users by various properties, such as:
- IP address (e.g., office IPs or VPNs)
- Email domain (e.g., @yourcompany.com)
- Custom user properties
- URL parameters (for test sessions)

Example: To exclude specific IPs
- Property: IP address
- Operator: does not contain
- Value: 192.168.1.1, 10.0.0.1 (use commas to separate multiple values)
Read this article to learn everything you need to know about Filters.
3. Use Multiple Filters if Needed
PostHog supports multiple rules at once, helping you build a comprehensive internal user exclusion filter. Combine filters like IP address + email domain for better accuracy.
4. Apply Globally or Per Insight
You can choose to:
- Toggle “Enable this filter on all new insights” for global filtering
- Or manually apply filters on individual reports or dashboards
Adding these filters ensures you’re analyzing clean, trustworthy data. This is especially important when you rely on PostHog for product decisions, marketing performance, or feature testing.
Conclusion
Setting up PostHog internal user filtering is one of the best ways to maintain clean analytics and improve decision-making. Whether you’re launching experiments or measuring product engagement, filtering out your internal team ensures your data reflects real users.
PostHog also has a detailed guide on this topic; you can check it out here.
More Tutorials You Might Like
If you found this guide helpful, check out our other tutorials to level up your analytics game:
PostHog Slack Integration: Send Event Alerts to Slack
Set Up a PostHog Alert for Your Website
Frequently asked qusetions
Does filtering internal users in PostHog delete their events or change billing?
No. The “Filter out internal and test users” feature works at the analysis level, not the ingestion level:
Events from internal users are still captured and stored in PostHog.
Filtering simply removes them from the insight or dashboard you’re looking at, so metrics don’t include that traffic.
If you want to stop sending internal data altogether (e.g. to reduce event volume), you need to handle that in your implementation: disable tracking on dev/staging hosts, add config checks, or avoid sending events for internal users.
Where do I turn PostHog’s “Filter out internal and test users” on or off?
There are two places involved:
Project settings – define which filters mark a user/session as internal.
Go to Project settings → “Filter out internal and test users”.
Add your filters there (email domains, IPs, hosts, cohorts, etc.).
Insight-level toggle – actually enable/disable the filter for a specific report.
When editing or creating an insight, use the “Filter out internal and test users” toggle in the filters panel.
ON = insights exclude traffic matching your internal filters. OFF = all traffic visible.
What’s the difference between project-level internal filters and insight-level filters?
Project-level filters (Settings):
Define how PostHog recognizes internal/test users (e.g. “email doesn’t contain @mycompany.com”, “host doesn’t equal localhost:3000”). These rules live in Project settings → Filter out internal and test users and are shared across all insights.Insight-level toggle:
Decides whether those project-level rules are applied to a specific graph, funnel, or dashboard. The toggle simply adds your internal filter group as extra filters whenever it’s turned on.
You can still add normal filters directly on an insight (e.g. “country = US”) even when the internal user filter is off.
How do I filter internal users by IP address in PostHog?
You have two main options:
Using the internal user settings (recommended for analysis):
Go to Project settings → “Filter out internal and test users”.
Add a filter on your IP-related property (e.g.
IP,ip, or a customoffice_ipproperty if you set one).Use an operation such as “doesn’t equal” or “doesn’t contain” with a comma-separated list of internal IPs or ranges.
Example pattern:
ip ∉ 1.2.3.4, 5.6.7.8(doesn’t contain these IPs)This means that when the toggle is on, PostHog will show events whose IP does not match your office IPs (i.e. real users).
At tracking time (for ingestion control):
If you want to avoid sending events at all from office IPs, implement logic in your backend or frontend to skip tracking when the request comes from a known internal IP.
How do I filter internal users by email domain or user properties?
The most stable approach is:
Use a person property like
emailand filter for “doesn’t contain @yourcompany.com” so you only see users who aren’t internal. PostHog’s own tutorial uses this pattern:email ∉ @posthog.com(“doesn’t contain”).Alternatively, add a dedicated boolean property like
is_employeeoris_test_userto your events or people and filter on that property.
Then add that filter in Project settings → Filter out internal and test users and toggle the feature on inside your insights.
How can I exclude QA or staging sessions using URL or host filters?
Very common pattern:
Host-based filters:
Add a filter on theHostproperty and exclude your dev environments, e.g.:Host ≠ localhost:8000, localhost:3000, staging.yourapp.comURL or query param filters:
If QA uses special URLs like?test_session=true, filter out events whereCurrent URLcontainstest_session=trueor where a custom propertyis_test_sessionis true.
You can combine these with email/IP filters so that both staging traffic and internal people on production are excluded when the toggle is on.
Can I use cohorts to manage internal users in PostHog?
Yes, and PostHog explicitly recommends it now for person-property–based internal filtering:
Create a cohort that defines internal users (e.g. email domain, role property, or custom flags).
In Project settings → Filter out internal and test users, add a filter like “Person is not in cohort Internal users”.
This gives you a single place to update who counts as internal (the cohort), which is cleaner when people join/leave the company or when you change criteria.
Why do I see fewer events in insights than in the Live / Activity view?
Live/Activity views often show all events as they arrive, while product analytics insights may apply:
Your “Filter out internal and test users” toggle
Any other filters on the insight or dashboard
If you’re missing events in charts but can see them in real-time views, the first thing to check is whether internal/test filtering is turned on and whether your filters are accidentally excluding too much traffic.
How should remote teams and VPN users be handled in internal filters?
IP-based filtering alone breaks down when:
People use dynamic home IPs
Everyone connects through a VPN or multiple exit nodes
In those cases, use identity-based filters instead of just network-based ones:
Email domain:
email doesn’t contain @yourcompany.comA boolean flag:
is_employee = trueCohorts built from HR / directory data
Then apply those cohorts or person properties in “Filter out internal and test users” so internal people are excluded regardless of where they’re connecting from. (+)
Does internal user filtering work for both PostHog Cloud and self-hosted?
Yes. The internal and test user filter is a product feature that works in both PostHog Cloud and self-hosted instances. The GitHub issue discussing confusion around the filter specifically references both environments.
The UI and behavior are essentially the same: you configure filters in project settings and toggle them per-insight.
What are common mistakes when setting up internal user filters in PostHog?
Some recurring problems PostHog has seen:
Using the wrong operator direction – e.g.
email contains @yourcompany.cominstead ofemail doesn’t contain @yourcompany.com, which can result in no data when the toggle is on. This has been common enough to be logged as a UX issue.
Filtering on properties that aren’t set everywhere, which can unintentionally drop events that don’t have that property.
Expecting filters to be retroactive on person changes – PostHog stores a snapshot of person properties at event time; removing or changing a property later doesn’t change historical events.
Double-check filter logic (“doesn’t contain” vs “contains”) and confirm which events actually have the properties you’re filtering on.
How can I confirm my internal filters are working correctly?
A simple validation workflow:
Use a known internal session:
Visit your app as an internal user (office IP, internal email, etc.) and trigger a few events.Check Live / Activity:
Confirm those events appear there.Open a test insight:
With the internal filter off, you should see those internal events.
With the filter on, those internal events should disappear from the graph or table.
If they’re still showing when the toggle is on, your filter conditions are likely too broad, pointed at the wrong property, or inverted (using “contains” instead of “doesn’t contain”).
Should I rely only on PostHog filters, or also prevent internal tracking in code?
Use both, for different reasons:
PostHog internal user filtering (this article):
Great for analysis – you keep all raw data but exclude internal users from reports, funnels, and dashboards.Instrumentation-level exclusion:
Useful when you want to avoid sending events at all from certain environments or users:Disable tracking on localhost and staging hosts
Add config flags that skip tracking for employees
Use backend checks to avoid logging internal system actions
For most teams, the practical setup is: disable obvious dev/staging noise in code, then use PostHog’s “Filter out internal and test users” to clean up anything that still makes it through.



