# Controlling data storage - Docs

This guide covers the various features available **after data reaches PostHog Cloud servers** to help you achieve your privacy goals. If you have data that cannot reach a third-party server like PostHog, please omit them during [data collection](/docs/privacy/data-collection.md).

This guide covers the following features:

| Feature | Description |
| --- | --- |
| [Data storage location](#data-storage-location) | Control where your data is physically stored for GDPR compliance |
| [Processing data before storage](#processing-data-before-storage) | Redact or filter data before it's stored in PostHog |
| [Data deletion](#data-deletion) | Tools to help comply with data deletion requests |
| [Data access control](#data-access-control) | Manage who can access what data in PostHog |

## Data storage location

If you require GDPR compliance, there are [specific guidelines](/docs/privacy/gdpr-compliance.md#you-should-not-transfer-eu-users-personal-data-outside-the-eu) on the location of data storage if you collect personal data. If you require robust GDPR compliance, we recommend using [PostHog Cloud EU](/eu.md) – a managed version of PostHog that's hosted on servers based in Frankfurt.

## Processing data before storage

PostHog supports [realtime transformations](/docs/cdp/transformations.md) of data **before it's stored in PostHog**. These transformations are applied to all events captured in realtime, so you can use them to:

-   [Hashing PII data](https://posthog.com/docs/cdp/transformations/template-hash-properties) before it's stored in PostHog
-   Disabling default [GeoIP enrichment transformations](https://posthog.com/docs/cdp/transformations/template-geoip)
-   [Dropping events](https://posthog.com/docs/cdp/transformations/drop-events) based on a filter
-   [IP anonymization](https://posthog.com/docs/cdp/transformations/template-ip-anonymization)

When in doubt, you can always create your own [custom transformation](https://app.posthog.com/pipeline/new/transformation/hog-template-blank-transformation). Custom transformations use the [Hog language](/docs/hog.md) to transform data.

### Discarding IP addresses at project level

You can configure your project to discard client IP addresses from stored events. Navigate to [**Settings** > **Project** > **IP data capture configuration**](https://app.posthog.com/settings/project#datacapture) and enable the **Discard client IP data** toggle.

When this setting is enabled:

-   Client IP addresses are **not stored** with your events
-   Transformations like [GeoIP enrichment](https://posthog.com/docs/cdp/transformations/template-geoip) and [bot detection](https://posthog.com/docs/cdp/transformations/template-bot-detection) can **still use the IP** before it is discarded

This allows you to enrich your events with location data or filter out bot traffic while ensuring raw IP addresses are not retained in your data.

See all default event properties collected

| Name | Key | Example value |
| --- | --- | --- |
| Timestamp | $timestamp | 2024-05-29T17:32:07.202Z |
| OS | $os | Mac OS X |
| OS Version | $os_version | 10.15.7 |
| Browser | $browser | Chrome |
| Browser Version | $browser_version | 125 |
| Device Type | $device_type | Desktop |
| Current URL | $current_url | https://example.com/page |
| Host | $host | example.com |
| Path Name | $pathname | /page |
| Screen Height | $screen_height | 1080 |
| Screen Width | $screen_width | 1920 |
| Viewport Height | $viewport_height | 950 |
| Viewport Width | $viewport_width | 1903 |
| Library | $lib | web |
| Library Version | $lib_version | 1.31.0 |
| Search Engine | $search_engine | google |
| Referrer URL | $referrer | https://google.com |
| Referring Domain | $referring_domain | www.google.com |
| Active Feature Flags | $active_feature_flags | ['beta_feature'] |
| Event Type | $event_type | click |
| UTM Source | $utm_source | newsletter |
| UTM Medium | $utm_medium | email |
| UTM Campaign | $utm_campaign | product_launch |
| UTM Term | $utm_term | new+product |
| UTM Content | $utm_content | logolink |
| Google Click ID | $gclid | TeSter-123 |
| Google Ads Source | $gad_source | google_ads |
| Google Search Ads 360 Click | $gclsrc | dsa |
| Google DoubleClick Click ID | $dclid | testDclid123 |
| Google Web-to-app Measure | $wbraid | testWbraid123 |
| Google App-to-web Measure | $gbraid | testGbraid123 |
| Facebook Click ID | $fbclid | testFbclid123 |
| Microsoft Click ID | $msclkid | testMsclkid123 |
| Twitter Click ID | $twclid | testTwclid123 |
| LinkedIn Ad Tracking ID | $la_fat_id | testLaFatId123 |
| Mailchimp Campaign ID | $mc_cid | testMcCid123 |
| Instagram Share Id | $igshid | testIgshid123 |
| TikTok Click ID | $ttclid | testTtclid123 |
| Plugins Succeeded | $plugins_succeeded | ['GeoIP (56578)'] |
| Plugins Failed | $plugins_failed | ['plugin3'] |
| Plugins Deferred | $plugins_deferred | ['plugin4'] |
| IP Address | $ip | 192.168.1.1 |

## Data deletion

You can remove unwanted data from PostHog by deleting groups and persons.

| What to delete | Where to delete | Additional details |
| --- | --- | --- |
| Your account | [Account settings](https://us.posthog.com/settings/user#user-delete) | Account is deleted immediately; all stored data about you is cleared within 30 days. See [deleting your account](/docs/settings/account-settings.md#deleting-your-account). |
| Projects | [Project settings](https://us.posthog.com/settings/project#project-delete) | All data under the project (including events) are automatically removed |
| Organizations | [Organization settings](https://us.posthog.com/settings/organization#organization-delete) | All data under the organization's projects (including events) are automatically removed |
| Persons | [In the persons tab](https://us.posthog.com/persons), [by API](#right-to-be-forgotten) | When a person is deleted, all events for that person can be deleted |

### Right to be forgotten

**Avoid reusing deleted distinct IDs**

User deletion requests are not immediate, but processed asynchronously. We recommend that you *avoid* reusing a deleted `distinct_id` value for a new user, as it may lead to unexpected results while the deletion is being processed. Once the deletion process is fully processed, PostHog does not retain any data associated with the deleted `distinct_id`.

If you must reuse the `distinct_id`, you can do so using the **Reset deleted person** tool, available from the dropdown at the top-right of the [**persons page**](https://app.posthog.com/persons). This tool enables you to reset a deleted `distinct_id` so that future events associated with it create a new person profile.

If you instead want to split a person with multiple IDs (e.g. to isolate bad data tied to a specific `distinct_id`), use the **Split IDs** button on their person profile.

Persons and events can be deleted using our API endpoints. This action requires a [personal API key](https://us.posthog.com/settings/user-api-keys).

To query all persons in your project, use the [GET Persons API endpoint](/docs/api/persons.md#get-api-projects-project_id-persons). You can filter for specific subsets of persons using the query parameters. For example, you can get a specific person by filtering by email:

PostHog AI

### Terminal

```bash
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl \
    -H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
    https://us.posthog.com/api/projects/:project_id/persons?email={EMAIL}
```

### JavaScript

```javascript
const response = await fetch('https://us.posthog.com/api/projects/:project_id/persons?email={EMAIL}', {
  headers: {
    'Authorization': 'Bearer [your personal api key]'
  }
})
```

### Python

```python
import requests
api_key = "[your personal api key]"
project_id = "[your project id]"
response = requests.get(
    "https://us.posthog.com/api/projects/{project_id}/persons?email={EMAIL}".format(
        project_id=project_id
    ),
    headers={"Authorization": "Bearer {}".format(api_key)},
).json()
```

To delete persons and their events, use the [DELETE Persons API endpoint](/docs/api/persons-4.md#post-api-projects-project_id-persons-bulk_delete) with the person's UUID (returned as `id` in the persons API response). To delete the person's corresponding events, add the `delete_events=true` parameter:

PostHog AI

### Terminal

```bash
curl -X DELETE "https://app.posthog.com/api/projects/<project_id>/persons/<person_uuid>?delete_events=true" \
     -H "Authorization: Bearer <personal_api_key>"
```

### JavaScript

```javascript
fetch('https://app.posthog.com/api/projects/<project_id>/persons/<person_uuid>?delete_events=true', {
  method: 'DELETE',
  headers: {
    'Authorization': 'Bearer <personal_api_key>'
  }
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```

### Python

```python
import requests
api_key = "<personal_api_key>"
project_id = "<project_id>"
person_uuid = "<person_uuid>"
url = "https://app.posthog.com/api/projects/{}/persons/{}?delete_events=true".format(
    project_id, person_uuid
)
headers = {"Authorization": "Bearer {}".format(api_key)}
response = requests.delete(url, headers=headers)
print(response.json())
```

This request will delete all events of the person(s) that have been captured before the deletion request.

### Manual data deletion

You can manually delete persons and their events in the PostHog UI:

-   Select **Persons** from the left-hand menu
-   Search for the person via their `distinct_id` or a property like email.
-   Click **view** next to the person within the search results
-   Click **Delete person** to remove them and all their associated data from the PostHog instance. You will be prompted to confirm this action.

### Asynchronous data deletion

While most data in PostHog is deleted instantly, event data is not. Instead data is cleared asynchronously during non-peak usage times (weekends on PostHog Cloud).

This is done because data deletion in [ClickHouse](/docs/how-posthog-works/clickhouse.md) is expensive and it can impact performance for other users.

## Data access control

An important part of protecting your users' privacy is to control who can access what data in PostHog. PostHog provides access control at 3 levels:

1.  [Organization level](/docs/settings/access-control.md#1-organization-level)
2.  [Project level](/docs/settings/access-control.md#2-project-level)
3.  [Resource level](/docs/settings/access-control.md#3-resource-level)

It's up to you to use these access control features to grant access to only the people who need to access the data.

You can follow this comprehensive guide to [access control](/docs/settings/access-control.md) to learn more.

### Community questions

Ask a question

### Was this page useful?

HelpfulCould be better