How to Redact PII from Google Gemini API Calls
Stop sending names, emails, and secrets to Google Gemini. Learn how to redact PII from every Gemini API call using a proxy-level security layer — no code changes required.
The problem: PII leaking through Gemini API calls
Every generateContent call sends your prompt to Google's servers. If that prompt includes user-submitted text — support tickets, form data, CRM records, medical notes — it almost certainly contains names, emails, phone numbers, and other personally identifiable information.
const result = await model.generateContent(
`Summarize this patient intake form:
Name: David Kim
Email: d.kim@healthcare.org
Phone: (312) 555-0187
SSN: 319-42-7756
DOB: 1975-08-22
Address: 1200 Lake Shore Dr, Chicago, IL 60610
Insurance ID: BCBS-449281003
Notes: Patient reports chronic back pain.
Internal API key: AIzaSyC-secret-key-here`
);
That single request just sent a name, email, phone number, SSN, date of birth, home address, insurance ID, and an API key to Google. Under GDPR, CCPA, and HIPAA, that's a compliance incident.
What PII looks like in Gemini payloads
Google's Gemini API accepts freeform text in the contents array. Any field your users can type into is a vector for PII leakage:
- Names and emails in support or healthcare contexts
- Phone numbers and addresses from CRM data
- SSNs and tax IDs in financial or HR workflows
- Medical record numbers in healthcare applications
- API keys and tokens accidentally pasted by developers
- Source code with hardcoded credentials
The API key in x-goog-api-key or your OAuth credentials are safe — they authenticate your requests. The problem is what's inside the request body.
The solution: proxy-level redaction with Grepture
Grepture is an open-source security proxy that sits between your application and Google Gemini. Every request is scanned for PII, secrets, and sensitive patterns before it leaves your infrastructure. Sensitive data is masked with reversible tokens — and restored in the response so your application works normally.
Your code doesn't change. Your prompts stay useful. Gemini never sees real PII.
Setup in 3 minutes
1. Install the SDK
npm install @grepture/sdk
2. Get your API key
Sign up at grepture.com/en/pricing — the free plan includes 1,000 requests/month. Copy your API key from the dashboard.
3. Wrap your Gemini client
Google's SDK authenticates via x-goog-api-key instead of the standard Authorization header. This requires a custom fetch wrapper that routes traffic through the Grepture proxy and forwards the API key correctly:
import { GoogleGenAI } from "@google/genai";
const GREPTURE_API_KEY = process.env.GREPTURE_API_KEY!;
const GEMINI_API_KEY = process.env.GEMINI_API_KEY!;
const PROXY_URL = "https://proxy.grepture.com";
const proxyFetch: typeof fetch = async (input, init) => {
const url =
typeof input === "string"
? input
: input instanceof URL
? input.toString()
: input.url;
const parsed = new URL(url);
const proxyUrl = `${PROXY_URL}/proxy${parsed.pathname}${parsed.search}`;
const headers = new Headers(init?.headers);
// Forward Google's API key via the Grepture auth-forward header
const googleApiKey = headers.get("x-goog-api-key");
if (googleApiKey) {
headers.set("X-Grepture-Auth-Forward", `Bearer ${googleApiKey}`);
}
// Authenticate with Grepture and set the target
headers.set("Authorization", `Bearer ${GREPTURE_API_KEY}`);
headers.set("X-Grepture-Target", url);
return globalThis.fetch(proxyUrl, { ...init, headers });
};
const ai = new GoogleGenAI({
apiKey: GEMINI_API_KEY,
httpOptions: { fetch: proxyFetch },
});
// Every request is now scanned and protected
const response = await ai.models.generateContent({
model: "gemini-2.5-flash",
contents: userInput,
});
The custom fetch intercepts every request, rewrites the URL to the Grepture proxy, and forwards Google's x-goog-api-key via the X-Grepture-Auth-Forward header. Google still authenticates your requests normally.
What gets detected
Grepture ships with 50+ detection patterns on the free tier and 80+ on Pro, covering:
| Category | Examples | Tier |
|---|---|---|
| Personal identifiers | Names, emails, phone numbers, SSNs, dates of birth | Free (regex), Pro (AI) |
| Financial data | Credit card numbers, IBANs, routing numbers | Free |
| Credentials | API keys, bearer tokens, passwords, connection strings | Free |
| Network identifiers | IP addresses, MAC addresses | Free |
| Freeform PII | Names, organizations, and addresses in unstructured text | Pro (local AI models) |
| Adversarial inputs | Prompt injection attempts | Business |
All detection runs on Grepture infrastructure — no data is forwarded to additional third parties.
Mask and restore: reversible redaction
Grepture doesn't just strip PII — it replaces sensitive values with tokens, sends the sanitized prompt to Gemini, and restores the original values in the response.
What Gemini sees:
Summarize this patient intake form:
Name: [PERSON_1]
Email: [EMAIL_1]
Phone: [PHONE_1]
SSN: [SSN_1]
DOB: [DATE_1]
Address: [ADDRESS_1]
...
What your app gets back:
The patient David Kim (d.kim@healthcare.org) reports
chronic back pain. They are located in Chicago, IL
and covered under BCBS insurance.
Gemini processes clean data. Your application receives the full, personalized response. No PII ever reaches Google.
Streaming support
Grepture handles Gemini's streaming responses natively. When you use generateContentStream, the proxy detokenizes chunks in real time — no buffering the entire response, no latency hit.
const stream = await ai.models.generateContentStream({
model: "gemini-2.5-flash",
contents: userInput,
});
for await (const chunk of stream) {
// Tokens are restored in real time
process.stdout.write(chunk.text ?? "");
}
Next steps
- View pricing — free for up to 1,000 requests/month
- Read the docs — SDK reference, configuration, and dashboard guide
- See how it works — architecture, detection rules, and zero-data mode