Torna al blog
Compliance

LGPD Compliance: The Ultimate Guide to Brazil’s Data Protection Law

Rachel Torres, Privacy CounselNovember 19, 202512 min di lettura
LGPDBrazilComplianceGlobal Privacy

TLDR: Brazil's LGPD has 10 legal bases (vs GDPR's 6), requires a DPO for all controllers, and caps fines at R$50M per violation. 150 million users. Enforcement is ramping up.

Read full summary Complete LGPD compliance guide covering consent requirements, legitimate interest differences, data protection officer obligations, and practical implementation for businesses targeting Brazilian users. Includes detailed comparison tables with GDPR, the full 10 legal bases for processing, CMP configuration for Brazilian visitors, Portuguese language consent flows, and TypeScript implementations for LGPD-compliant consent management. *Summary by Claude AI*
## Latin America's Privacy Giant Brazil has 150 million internet users. More than Germany, France, and Spain combined. The e-commerce market exceeds $30 billion annually and grows 20% year over year. If you're building a global business and ignoring Brazil, you're leaving money on the table. But here's what catches companies off guard: Brazil doesn't just have a privacy law. Brazil has a privacy law that's *different* from GDPR in ways that matter. The Lei Geral de Proteção de Dados (LGPD) looks like GDPR's younger sibling. Same principles. Similar rights. Comparable structure. But the devil lives in the details—and those details will trip you up if you assume "GDPR-compliant" equals "LGPD-compliant." **Ten legal bases instead of six.** LGPD adds grounds for processing that GDPR doesn't recognize, including credit protection and healthcare protection. Use the wrong basis and your processing becomes unlawful. **DPO required for everyone.** GDPR only mandates Data Protection Officers for public bodies and large-scale processors. LGPD requires a DPO for *all* data controllers. Small startup serving Brazilian users? You need a DPO. **Consent is revocable at any time.** Sounds similar to GDPR, but LGPD explicitly requires that withdrawal be as easy as giving consent. No friction. No confirmation dialogs. One click revoke. **Children means under 18.** Not under 16 like GDPR. Any data from anyone under 18 requires parental consent with "best interest of the child" as the guiding principle. The ANPD (Brazil's data protection authority) spent the first two years after LGPD's enforcement building infrastructure. Now they're enforcing. Fines are capped at R$50 million (~$10M USD) per violation—not per-revenue percentages like GDPR—but violations add up fast when you're processing 150 million users' data. ## LGPD vs. GDPR: A Detailed Comparison Understanding the differences between LGPD and GDPR is essential for organizations that must comply with both: | Feature | GDPR (EU) | LGPD (Brazil) | |---------|-----------|---------------| | **Effective Date** | May 25, 2018 | August 16, 2020 (sanctions from August 2021) | | **Territorial Scope** | Processing of EU residents' data | Processing of data in Brazil OR offering services to Brazil | | **Legal Bases for Processing** | 6 legal bases | 10 legal bases | | **Breach Notification** | 72 hours to supervisory authority | "Reasonable time" to ANPD and data subjects | | **DPO Requirement** | Required for specific cases (public bodies, large-scale processing) | Required for ALL data controllers (with exceptions for small businesses) | | **Maximum Fines** | €20M or 4% of global annual revenue | 2% of Brazil revenue, capped at R$50M (~$10M USD) per violation | | **International Transfers** | Adequacy decisions, SCCs, BCRs | Adequacy decisions, SCCs, specific consent | | **Data Subject Rights** | 8 rights | 9 rights (includes anonymization) | | **Children's Data** | Under 16 requires parental consent | Under 18 requires parental consent (with best interest principle) | | **Regulatory Authority** | National DPAs | ANPD (single federal authority) | ## The 10 Legal Bases Under LGPD Unlike GDPR's 6 legal bases, LGPD provides 10 grounds for lawful processing. This is one of the most significant differences: ```typescript interface LGPDLegalBasis { id: number; portugueseName: string; englishName: string; article: string; description: string; gdprEquivalent: string | null; useCases: string[]; requirements: string[]; } const lgpdLegalBases: LGPDLegalBasis[] = [ { id: 1, portugueseName: 'Consentimento', englishName: 'Consent', article: 'Art. 7, I', description: 'Processing based on free, informed, and unambiguous consent from the data subject.', gdprEquivalent: 'Art. 6(1)(a)', useCases: [ 'Marketing communications', 'Newsletter subscriptions', 'Cookies and tracking', 'Third-party data sharing' ], requirements: [ 'Must be freely given', 'Must be specific to the purpose', 'Can be revoked at any time', 'Proof of consent must be documented' ] }, { id: 2, portugueseName: 'Cumprimento de obrigação legal', englishName: 'Legal Obligation', article: 'Art. 7, II', description: 'Processing necessary for compliance with legal or regulatory obligations.', gdprEquivalent: 'Art. 6(1)(c)', useCases: [ 'Tax reporting', 'Employment records', 'Anti-money laundering', 'Consumer protection compliance' ], requirements: [ 'Must cite specific law or regulation', 'Processing must be necessary for compliance', 'Document the legal requirement' ] }, { id: 3, portugueseName: 'Execução de políticas públicas', englishName: 'Execution of Public Policies', article: 'Art. 7, III', description: 'Processing by public administration for execution of public policies.', gdprEquivalent: 'Art. 6(1)(e) (partially)', useCases: [ 'Government health programs', 'Educational initiatives', 'Social welfare programs', 'Public safety measures' ], requirements: [ 'Only for public administration bodies', 'Policy must be established in law/regulation', 'Subject to transparency requirements' ] }, { id: 4, portugueseName: 'Estudos e pesquisas', englishName: 'Research Studies', article: 'Art. 7, IV', description: 'Processing for conducting research studies, preferably with anonymized data.', gdprEquivalent: 'Art. 6(1)(e) combined with Art. 89', useCases: [ 'Academic research', 'Market research', 'Statistical analysis', 'Scientific studies' ], requirements: [ 'Preferably use anonymized data', 'Must be conducted by research organizations', 'Appropriate safeguards required' ] }, { id: 5, portugueseName: 'Execução de contrato', englishName: 'Contract Performance', article: 'Art. 7, V', description: 'Processing necessary for the execution of a contract or pre-contractual procedures.', gdprEquivalent: 'Art. 6(1)(b)', useCases: [ 'Processing orders', 'Providing contracted services', 'Pre-contract quotes', 'Account management' ], requirements: [ 'Must be necessary for contract', 'Data subject must be party to contract', 'Cannot extend beyond contract scope' ] }, { id: 6, portugueseName: 'Exercício regular de direitos', englishName: 'Exercise of Rights in Legal Proceedings', article: 'Art. 7, VI', description: 'Processing for exercising rights in judicial, administrative, or arbitration proceedings.', gdprEquivalent: 'No direct equivalent (closest: Art. 6(1)(f))', useCases: [ 'Litigation support', 'Administrative proceedings', 'Arbitration', 'Defense against claims' ], requirements: [ 'Must be related to actual or potential proceedings', 'Processing must be necessary', 'Proportionality principle applies' ] }, { id: 7, portugueseName: 'Proteção da vida', englishName: 'Protection of Life or Physical Safety', article: 'Art. 7, VII', description: 'Processing to protect the life or physical safety of the data subject or third party.', gdprEquivalent: 'Art. 6(1)(d)', useCases: [ 'Medical emergencies', 'Disaster response', 'Security emergencies', 'Life-threatening situations' ], requirements: [ 'Must involve genuine threat to life/safety', 'Other legal bases not available', 'Emergency context required' ] }, { id: 8, portugueseName: 'Tutela da saúde', englishName: 'Health Protection', article: 'Art. 7, VIII', description: 'Processing for health protection purposes by health professionals or health authorities.', gdprEquivalent: 'Art. 9(2)(h) and (i)', useCases: [ 'Healthcare provision', 'Public health monitoring', 'Health system management', 'Disease prevention' ], requirements: [ 'Must be performed by health professionals/authorities', 'Subject to professional secrecy', 'Public health purposes' ] }, { id: 9, portugueseName: 'Interesses legítimos', englishName: 'Legitimate Interest', article: 'Art. 7, IX', description: 'Processing for legitimate interests of controller or third party, respecting data subject rights.', gdprEquivalent: 'Art. 6(1)(f)', useCases: [ 'Fraud prevention', 'IT security', 'Business analytics (limited)', 'Direct marketing to existing customers' ], requirements: [ 'Legitimate interest must be documented', 'Balancing test required', 'Rights of data subject must be respected', 'Transparency about processing' ] }, { id: 10, portugueseName: 'Proteção do crédito', englishName: 'Credit Protection', article: 'Art. 7, X', description: 'Processing for credit protection purposes, including credit scoring.', gdprEquivalent: 'No direct equivalent', useCases: [ 'Credit scoring', 'Credit bureau operations', 'Loan assessments', 'Financial risk analysis' ], requirements: [ 'Must comply with specific credit legislation', 'Consumer Code protections apply', 'Right to explanation of scoring' ] } ]; ``` ## Legal Basis Selection Engine for LGPD Building on these 10 legal bases, here's a system to help select the appropriate legal basis: ```typescript interface ProcessingScenario { description: string; dataCategories: string[]; purposes: string[]; dataSubjectType: 'customer' | 'prospect' | 'employee' | 'public' | 'child'; isController: boolean; sector: 'private' | 'public' | 'healthcare' | 'financial'; involvesSensitiveData: boolean; involvesAutomatedDecisions: boolean; } interface LegalBasisRecommendation { primaryBasis: LGPDLegalBasis; alternativeBases: LGPDLegalBasis[]; reasoning: string; requirements: string[]; warnings: string[]; } class LGPDLegalBasisSelector { selectLegalBasis(scenario: ProcessingScenario): LegalBasisRecommendation { const recommendations: LegalBasisRecommendation = { primaryBasis: lgpdLegalBases[0], // Default to consent alternativeBases: [], reasoning: '', requirements: [], warnings: [] }; // Healthcare sector - special handling if (scenario.sector === 'healthcare') { recommendations.primaryBasis = lgpdLegalBases[7]; // Health Protection recommendations.reasoning = 'Healthcare sector processing should primarily rely on health protection basis (Art. 7, VIII).'; recommendations.requirements = [ 'Processing must be by health professionals or authorities', 'Professional secrecy obligations apply', 'Document public health purpose if applicable' ]; if (scenario.involvesSensitiveData) { recommendations.warnings.push( 'Sensitive health data - additional safeguards required under Art. 11' ); } return recommendations; } // Financial sector - credit protection available if (scenario.sector === 'financial' && scenario.purposes.some(p => p.toLowerCase().includes('credit'))) { recommendations.primaryBasis = lgpdLegalBases[9]; // Credit Protection recommendations.reasoning = 'Credit-related processing can rely on the credit protection basis (Art. 7, X), unique to LGPD.'; recommendations.requirements = [ 'Comply with Consumer Defense Code', 'Comply with Credit Bureau Law (Lei do Cadastro Positivo)', 'Provide clear information about scoring methodology', 'Enable data subject access to their credit information' ]; recommendations.warnings.push( 'Credit scoring decisions must be explainable under Art. 20' ); return recommendations; } // Public administration if (scenario.sector === 'public') { recommendations.primaryBasis = lgpdLegalBases[2]; // Public Policies recommendations.alternativeBases = [lgpdLegalBases[1]]; // Legal Obligation recommendations.reasoning = 'Public administration should use public policy execution basis (Art. 7, III).'; recommendations.requirements = [ 'Policy must be provided for by law or regulation', 'Enhanced transparency requirements', 'Purpose limitation strictly enforced' ]; return recommendations; } // Contract-related processing if (scenario.purposes.some(p => p.toLowerCase().includes('contract') || p.toLowerCase().includes('order') || p.toLowerCase().includes('service delivery'))) { recommendations.primaryBasis = lgpdLegalBases[4]; // Contract Performance recommendations.reasoning = 'Processing for contract execution uses Art. 7, V basis.'; recommendations.requirements = [ 'Processing must be necessary for contract', 'Data subject must be party to the contract', 'Cannot process beyond contract scope' ]; return recommendations; } // Marketing and tracking - consent required if (scenario.purposes.some(p => p.toLowerCase().includes('marketing') || p.toLowerCase().includes('tracking') || p.toLowerCase().includes('profiling') || p.toLowerCase().includes('advertising'))) { recommendations.primaryBasis = lgpdLegalBases[0]; // Consent recommendations.reasoning = 'Marketing and tracking activities require explicit consent (Art. 7, I).'; recommendations.requirements = [ 'Consent must be free, informed, and specific', 'Provide granular options for different purposes', 'Easy withdrawal mechanism required', 'Document proof of consent' ]; if (scenario.dataSubjectType === 'child') { recommendations.warnings.push( 'Children under 18 require parental consent - Art. 14' ); } return recommendations; } // Children's data - always requires special handling if (scenario.dataSubjectType === 'child') { recommendations.primaryBasis = lgpdLegalBases[0]; // Consent recommendations.reasoning = 'Processing children\'s data requires specific parental consent under Art. 14.'; recommendations.requirements = [ 'Obtain consent from parent or legal guardian', 'Process only data strictly necessary', 'Best interest of child must be considered', 'Age-appropriate privacy information', 'Parental verification mechanism' ]; recommendations.warnings.push( 'LGPD defines children as under 18, stricter than GDPR' ); return recommendations; } // Legal proceedings if (scenario.purposes.some(p => p.toLowerCase().includes('legal') || p.toLowerCase().includes('litigation') || p.toLowerCase().includes('defense'))) { recommendations.primaryBasis = lgpdLegalBases[5]; // Exercise of Rights recommendations.reasoning = 'Processing for legal proceedings uses Art. 7, VI basis.'; recommendations.requirements = [ 'Must relate to actual or anticipated proceedings', 'Proportional to the legal purpose', 'Document the legal necessity' ]; return recommendations; } // Fraud prevention and security - legitimate interest if (scenario.purposes.some(p => p.toLowerCase().includes('fraud') || p.toLowerCase().includes('security'))) { recommendations.primaryBasis = lgpdLegalBases[8]; // Legitimate Interest recommendations.alternativeBases = [lgpdLegalBases[0]]; // Consent as alternative recommendations.reasoning = 'Fraud prevention and security can use legitimate interest (Art. 7, IX).'; recommendations.requirements = [ 'Document the legitimate interest', 'Conduct balancing test', 'Ensure transparency about processing', 'Provide opt-out where possible' ]; return recommendations; } // Default to consent for any unclear scenarios recommendations.primaryBasis = lgpdLegalBases[0]; recommendations.reasoning = 'When in doubt, consent provides the safest legal basis.'; recommendations.requirements = [ 'Obtain free, informed, specific consent', 'Provide clear privacy information', 'Enable easy consent withdrawal', 'Maintain consent records' ]; return recommendations; } } ``` ## Implementing LGPD-Compliant Consent Your Consent Management Platform must handle LGPD-specific requirements, including Portuguese language support and the unique legal bases: ```typescript interface LGPDConsentConfig { language: 'pt-BR'; purposes: LGPDPurpose[]; cookieCategories: LGPDCookieCategory[]; dataSubjectRights: LGPDRight[]; consentSettings: { defaultState: 'opt-out' | 'opt-in'; requireExplicitConsent: boolean; allowGranularConsent: boolean; showPurposeDescriptions: boolean; showLegalBasis: boolean; }; } interface LGPDPurpose { id: string; namePortuguese: string; nameEnglish: string; descriptionPortuguese: string; descriptionEnglish: string; legalBasisId: number; isRequired: boolean; retentionPeriod: string; dataCategories: string[]; thirdPartySharing: boolean; internationalTransfer: boolean; } interface LGPDCookieCategory { id: string; namePortuguese: string; nameEnglish: string; descriptionPortuguese: string; descriptionEnglish: string; isEssential: boolean; defaultEnabled: boolean; requiresConsent: boolean; } interface LGPDRight { id: string; article: string; namePortuguese: string; nameEnglish: string; description: string; } class LGPDConsentManager { private config: LGPDConsentConfig; private consentState: Map = new Map(); constructor(config: LGPDConsentConfig) { this.config = config; this.initializeDefaultConfig(); } private initializeDefaultConfig(): void { // Define standard LGPD data subject rights this.config.dataSubjectRights = [ { id: 'confirmation', article: 'Art. 18, I', namePortuguese: 'Confirmação da existência de tratamento', nameEnglish: 'Confirmation of processing', description: 'Right to confirm whether personal data is being processed' }, { id: 'access', article: 'Art. 18, II', namePortuguese: 'Acesso aos dados', nameEnglish: 'Access to data', description: 'Right to access personal data being processed' }, { id: 'correction', article: 'Art. 18, III', namePortuguese: 'Correção de dados incompletos, inexatos ou desatualizados', nameEnglish: 'Correction of data', description: 'Right to correct incomplete, inaccurate, or outdated data' }, { id: 'anonymization', article: 'Art. 18, IV', namePortuguese: 'Anonimização, bloqueio ou eliminação de dados desnecessários', nameEnglish: 'Anonymization, blocking, or deletion', description: 'Right to anonymization, blocking, or deletion of unnecessary data' }, { id: 'portability', article: 'Art. 18, V', namePortuguese: 'Portabilidade dos dados', nameEnglish: 'Data portability', description: 'Right to data portability to another service provider' }, { id: 'deletion', article: 'Art. 18, VI', namePortuguese: 'Eliminação dos dados pessoais tratados com consentimento', nameEnglish: 'Deletion of data', description: 'Right to deletion of data processed based on consent' }, { id: 'information_sharing', article: 'Art. 18, VII', namePortuguese: 'Informação sobre compartilhamento', nameEnglish: 'Information about sharing', description: 'Right to information about entities with whom data is shared' }, { id: 'consent_info', article: 'Art. 18, VIII', namePortuguese: 'Informação sobre não fornecimento de consentimento', nameEnglish: 'Information about non-consent', description: 'Right to information about consequences of not providing consent' }, { id: 'revocation', article: 'Art. 18, IX', namePortuguese: 'Revogação do consentimento', nameEnglish: 'Consent revocation', description: 'Right to revoke consent at any time' } ]; } generateConsentBanner(): LGPDBanner { return { title: 'Política de Privacidade e Cookies', introduction: `Utilizamos cookies e tecnologias semelhantes para melhorar sua experiência em nosso site. De acordo com a Lei Geral de Proteção de Dados (LGPD), solicitamos seu consentimento para o tratamento de seus dados pessoais.`, categories: this.config.cookieCategories.map(cat => ({ id: cat.id, name: cat.namePortuguese, description: cat.descriptionPortuguese, isRequired: cat.isEssential, defaultEnabled: cat.defaultEnabled })), buttons: { acceptAll: 'Aceitar Todos', rejectAll: 'Rejeitar Todos', customize: 'Personalizar', save: 'Salvar Preferências' }, links: { privacyPolicy: '/politica-de-privacidade', cookiePolicy: '/politica-de-cookies', dataSubjectRights: '/seus-direitos' }, footer: 'Você pode alterar suas preferências a qualquer momento.' }; } generatePreferenceCenter(): LGPDPreferenceCenter { return { title: 'Centro de Preferências de Privacidade', sections: [ { id: 'purposes', title: 'Finalidades do Tratamento', description: 'Selecione quais finalidades você autoriza para o tratamento dos seus dados pessoais.', items: this.config.purposes.map(p => ({ id: p.id, name: p.namePortuguese, description: p.descriptionPortuguese, legalBasis: this.getLegalBasisDescription(p.legalBasisId), retentionPeriod: p.retentionPeriod, isRequired: p.isRequired, thirdPartySharing: p.thirdPartySharing, internationalTransfer: p.internationalTransfer })) }, { id: 'cookies', title: 'Categorias de Cookies', description: 'Gerencie quais tipos de cookies são utilizados durante sua navegação.', items: this.config.cookieCategories.map(c => ({ id: c.id, name: c.namePortuguese, description: c.descriptionPortuguese, isRequired: c.isEssential, defaultEnabled: c.defaultEnabled })) }, { id: 'rights', title: 'Seus Direitos', description: 'De acordo com a LGPD, você tem os seguintes direitos sobre seus dados pessoais.', items: this.config.dataSubjectRights.map(r => ({ id: r.id, name: r.namePortuguese, description: r.description, article: r.article })) } ], dpoContact: { title: 'Encarregado de Proteção de Dados (DPO)', description: 'Para exercer seus direitos ou esclarecer dúvidas sobre o tratamento de seus dados, entre em contato:', email: '[email protected]', phone: '+55 11 XXXX-XXXX' } }; } recordConsent( userId: string, consents: Array<{ purposeId: string; granted: boolean }>, metadata: ConsentMetadata ): ConsentRecord { const record: ConsentRecord = { id: this.generateRecordId(), userId, timestamp: new Date(), consents: consents.map(c => ({ purposeId: c.purposeId, granted: c.granted, legalBasisId: this.config.purposes.find(p => p.id === c.purposeId)?.legalBasisId || 1 })), metadata: { ...metadata, lgpdVersion: '2018', consentMethod: 'explicit', language: 'pt-BR' }, proofOfConsent: this.generateProofOfConsent(userId, consents, metadata) }; this.consentState.set(userId, record); this.persistConsentRecord(record); return record; } revokeConsent(userId: string, purposeIds?: string[]): ConsentRevocation { const existingRecord = this.consentState.get(userId); const revocation: ConsentRevocation = { id: this.generateRecordId(), userId, timestamp: new Date(), revokedPurposes: purposeIds || existingRecord?.consents.map(c => c.purposeId) || [], previousConsent: existingRecord || null, confirmation: 'Seu consentimento foi revogado com sucesso.' }; // Update consent state if (existingRecord) { existingRecord.consents = existingRecord.consents.map(c => ({ ...c, granted: purposeIds ? !purposeIds.includes(c.purposeId) && c.granted : false })); this.consentState.set(userId, existingRecord); } this.persistRevocation(revocation); this.triggerDataDeletionWorkflow(userId, revocation.revokedPurposes); return revocation; } handleDataSubjectRequest( userId: string, rightId: string, details: string ): DataSubjectRequestResponse { const right = this.config.dataSubjectRights.find(r => r.id === rightId); if (!right) { throw new Error('Invalid right ID'); } const response: DataSubjectRequestResponse = { requestId: this.generateRecordId(), userId, rightExercised: right, submittedAt: new Date(), expectedResponseDate: this.calculateResponseDeadline(), status: 'received', confirmationMessage: `Sua solicitação de ${right.namePortuguese} foi recebida. Responderemos em até 15 dias conforme previsto na LGPD.` }; this.persistDataSubjectRequest(response, details); return response; } private getLegalBasisDescription(legalBasisId: number): string { const basis = lgpdLegalBases.find(b => b.id === legalBasisId); return basis ? `${basis.portugueseName} (${basis.article})` : 'Não especificado'; } private generateProofOfConsent( userId: string, consents: Array<{ purposeId: string; granted: boolean }>, metadata: ConsentMetadata ): ProofOfConsent { return { hash: this.generateHash(JSON.stringify({ userId, consents, metadata })), timestamp: new Date().toISOString(), userAgent: metadata.userAgent, ipAddress: metadata.ipAddress, consentText: this.getCurrentConsentText(), version: '1.0' }; } private generateHash(data: string): string { // In production, use crypto library return `lgpd_consent_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; } private generateRecordId(): string { return `rec_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; } private calculateResponseDeadline(): Date { // LGPD requires response within 15 days (can be extended in complex cases) const deadline = new Date(); deadline.setDate(deadline.getDate() + 15); return deadline; } private getCurrentConsentText(): string { return `Ao clicar em "Aceitar", você concorda com o tratamento de seus dados pessoais conforme descrito em nossa Política de Privacidade, em conformidade com a Lei Geral de Proteção de Dados (Lei nº 13.709/2018).`; } private persistConsentRecord(record: ConsentRecord): void { // Implement persistence to database console.log('Persisting consent record:', record.id); } private persistRevocation(revocation: ConsentRevocation): void { // Implement persistence to database console.log('Persisting revocation:', revocation.id); } private persistDataSubjectRequest( response: DataSubjectRequestResponse, details: string ): void { // Implement persistence to database console.log('Persisting DSR:', response.requestId); } private triggerDataDeletionWorkflow(userId: string, purposes: string[]): void { // Trigger deletion workflow for consent-based processing console.log(`Triggering deletion workflow for user ${userId}, purposes: ${purposes.join(', ')}`); } } interface LGPDBanner { title: string; introduction: string; categories: Array<{ id: string; name: string; description: string; isRequired: boolean; defaultEnabled: boolean; }>; buttons: { acceptAll: string; rejectAll: string; customize: string; save: string; }; links: { privacyPolicy: string; cookiePolicy: string; dataSubjectRights: string; }; footer: string; } interface LGPDPreferenceCenter { title: string; sections: Array<{ id: string; title: string; description: string; items: any[]; }>; dpoContact: { title: string; description: string; email: string; phone: string; }; } interface ConsentRecord { id: string; userId: string; timestamp: Date; consents: Array<{ purposeId: string; granted: boolean; legalBasisId: number; }>; metadata: ConsentMetadata & { lgpdVersion: string; consentMethod: string; language: string; }; proofOfConsent: ProofOfConsent; } interface ConsentMetadata { userAgent: string; ipAddress: string; pageUrl: string; } interface ProofOfConsent { hash: string; timestamp: string; userAgent: string; ipAddress: string; consentText: string; version: string; } interface ConsentRevocation { id: string; userId: string; timestamp: Date; revokedPurposes: string[]; previousConsent: ConsentRecord | null; confirmation: string; } interface DataSubjectRequestResponse { requestId: string; userId: string; rightExercised: LGPDRight; submittedAt: Date; expectedResponseDate: Date; status: 'received' | 'processing' | 'completed' | 'rejected'; confirmationMessage: string; } ``` ## Detecting Brazilian Visitors Your CMP should automatically detect Brazilian visitors and serve the appropriate Portuguese-language consent experience: ```typescript interface GeoDetectionResult { country: string; countryCode: string; region?: string; city?: string; timezone?: string; isInBrazil: boolean; appliesLGPD: boolean; } interface LanguagePreference { browserLanguage: string; preferredLanguage: string; isPortuguese: boolean; } class BrazilianVisitorDetector { private geoIPProvider: string; constructor(geoIPProvider: string = 'maxmind') { this.geoIPProvider = geoIPProvider; } async detectLocation(ipAddress: string): Promise { // In production, use a GeoIP service like MaxMind const geoData = await this.queryGeoIP(ipAddress); return { country: geoData.country, countryCode: geoData.countryCode, region: geoData.region, city: geoData.city, timezone: geoData.timezone, isInBrazil: geoData.countryCode === 'BR', appliesLGPD: this.determineIfLGPDApplies(geoData) }; } detectLanguagePreference(acceptLanguageHeader: string): LanguagePreference { const languages = this.parseAcceptLanguage(acceptLanguageHeader); const browserLanguage = languages[0] || 'en'; const isPortuguese = languages.some(lang => lang.toLowerCase().startsWith('pt') ); return { browserLanguage, preferredLanguage: isPortuguese ? 'pt-BR' : browserLanguage, isPortuguese }; } shouldShowLGPDConsent( geoResult: GeoDetectionResult, languagePreference: LanguagePreference, userSettings?: { forceLGPD?: boolean } ): LGPDConsentDecision { // User explicitly requested LGPD if (userSettings?.forceLGPD) { return { showLGPD: true, reason: 'user_requested', language: 'pt-BR' }; } // User is in Brazil if (geoResult.isInBrazil) { return { showLGPD: true, reason: 'location_brazil', language: 'pt-BR' }; } // User's browser is in Portuguese (might be Brazilian abroad) if (languagePreference.isPortuguese) { return { showLGPD: true, reason: 'language_portuguese', language: 'pt-BR' }; } // Check if LGPD applies based on service targeting if (geoResult.appliesLGPD) { return { showLGPD: true, reason: 'service_targets_brazil', language: languagePreference.isPortuguese ? 'pt-BR' : 'en' }; } return { showLGPD: false, reason: 'not_applicable', language: languagePreference.preferredLanguage }; } private determineIfLGPDApplies(geoData: GeoIPData): boolean { // LGPD applies if: // 1. Data subject is in Brazil // 2. Processing occurs in Brazil // 3. Services are offered to Brazilian market if (geoData.countryCode === 'BR') { return true; } // Additional logic for service targeting could be added here return false; } private async queryGeoIP(ipAddress: string): Promise { // Placeholder - implement with actual GeoIP service return { country: 'Brazil', countryCode: 'BR', region: 'São Paulo', city: 'São Paulo', timezone: 'America/Sao_Paulo' }; } private parseAcceptLanguage(header: string): string[] { if (!header) return []; return header .split(',') .map(part => { const [lang, qValue] = part.trim().split(';q='); return { lang: lang.trim(), quality: qValue ? parseFloat(qValue) : 1.0 }; }) .sort((a, b) => b.quality - a.quality) .map(item => item.lang); } } interface GeoIPData { country: string; countryCode: string; region?: string; city?: string; timezone?: string; } interface LGPDConsentDecision { showLGPD: boolean; reason: 'user_requested' | 'location_brazil' | 'language_portuguese' | 'service_targets_brazil' | 'not_applicable'; language: string; } ``` ## ANPD Enforcement and Compliance The ANPD (Autoridade Nacional de Proteção de Dados) is Brazil's data protection authority. Understanding its enforcement approach is crucial: ```typescript interface ANPDEnforcementInfo { sanctionTypes: SanctionType[]; enforcementPriorities: string[]; complianceGuidelines: ComplianceGuideline[]; recentActions: EnforcementAction[]; } interface SanctionType { name: string; namePortuguese: string; description: string; maxPenalty?: string; article: string; } interface ComplianceGuideline { id: string; title: string; titlePortuguese: string; publicationDate: Date; summary: string; url: string; } interface EnforcementAction { date: Date; organization: string; violation: string; sanction: string; amount?: string; } const anpdSanctions: SanctionType[] = [ { name: 'Warning', namePortuguese: 'Advertência', description: 'Warning with deadline for adopting corrective measures', article: 'Art. 52, I' }, { name: 'Simple Fine', namePortuguese: 'Multa Simples', description: 'Fine of up to 2% of revenue, limited to R$50 million per violation', maxPenalty: 'R$50,000,000 or 2% of Brazil revenue', article: 'Art. 52, II' }, { name: 'Daily Fine', namePortuguese: 'Multa Diária', description: 'Daily fine to compel compliance with ANPD orders', maxPenalty: 'R$50,000,000 total', article: 'Art. 52, III' }, { name: 'Publicization', namePortuguese: 'Publicização da Infração', description: 'Public disclosure of the violation after confirmed', article: 'Art. 52, IV' }, { name: 'Data Blocking', namePortuguese: 'Bloqueio dos Dados', description: 'Blocking of personal data related to the violation', article: 'Art. 52, V' }, { name: 'Data Deletion', namePortuguese: 'Eliminação dos Dados', description: 'Mandatory deletion of personal data related to the violation', article: 'Art. 52, VI' }, { name: 'Partial Processing Suspension', namePortuguese: 'Suspensão Parcial do Banco de Dados', description: 'Partial suspension of database operations for up to 6 months', article: 'Art. 52, X' }, { name: 'Full Processing Suspension', namePortuguese: 'Suspensão do Exercício da Atividade de Tratamento', description: 'Complete suspension of processing activities for up to 6 months', article: 'Art. 52, XI' }, { name: 'Processing Prohibition', namePortuguese: 'Proibição Parcial ou Total do Tratamento', description: 'Partial or total prohibition of processing activities', article: 'Art. 52, XII' } ]; class ANPDComplianceChecker { checkCompliance(organization: OrganizationProfile): ComplianceReport { const issues: ComplianceIssue[] = []; const recommendations: string[] = []; // Check DPO appointment (mandatory for all controllers) if (!organization.hasDPO) { issues.push({ severity: 'high', category: 'governance', issue: 'No DPO appointed', issuePortuguese: 'Encarregado (DPO) não nomeado', article: 'Art. 41', recommendation: 'Appoint a Data Protection Officer and publish contact information' }); } // Check privacy policy if (!organization.hasPrivacyPolicy) { issues.push({ severity: 'high', category: 'transparency', issue: 'No privacy policy published', issuePortuguese: 'Política de privacidade não publicada', article: 'Art. 9', recommendation: 'Publish a comprehensive privacy policy in Portuguese' }); } else if (!organization.privacyPolicyInPortuguese) { issues.push({ severity: 'medium', category: 'transparency', issue: 'Privacy policy not in Portuguese', issuePortuguese: 'Política de privacidade não está em português', article: 'Art. 9', recommendation: 'Provide privacy policy in Portuguese for Brazilian users' }); } // Check consent mechanisms if (!organization.hasConsentMechanism) { issues.push({ severity: 'high', category: 'consent', issue: 'No consent mechanism implemented', issuePortuguese: 'Mecanismo de consentimento não implementado', article: 'Art. 7, I', recommendation: 'Implement LGPD-compliant consent collection' }); } // Check data subject rights implementation if (!organization.hasDataSubjectRightsPortal) { issues.push({ severity: 'medium', category: 'rights', issue: 'No data subject rights portal', issuePortuguese: 'Portal de direitos do titular não implementado', article: 'Art. 18', recommendation: 'Implement a portal for data subjects to exercise their rights' }); } // Check security measures if (!organization.hasSecurityMeasures) { issues.push({ severity: 'high', category: 'security', issue: 'Inadequate security measures', issuePortuguese: 'Medidas de segurança inadequadas', article: 'Art. 46', recommendation: 'Implement technical and administrative security measures' }); } // Check breach notification procedures if (!organization.hasBreachProcedures) { issues.push({ severity: 'high', category: 'incident_response', issue: 'No breach notification procedures', issuePortuguese: 'Procedimentos de notificação de incidentes não estabelecidos', article: 'Art. 48', recommendation: 'Establish incident response and breach notification procedures' }); } // Check international transfer compliance if (organization.transfersDataInternationally && !organization.hasInternationalTransferMechanisms) { issues.push({ severity: 'high', category: 'transfers', issue: 'International transfers without adequate safeguards', issuePortuguese: 'Transferências internacionais sem garantias adequadas', article: 'Art. 33', recommendation: 'Implement appropriate mechanisms for international data transfers' }); } // Check children's data handling if (organization.processesChildrensData && !organization.hasParentalConsentMechanism) { issues.push({ severity: 'high', category: 'children', issue: 'Processing children\'s data without proper consent', issuePortuguese: 'Tratamento de dados de crianças sem consentimento adequado', article: 'Art. 14', recommendation: 'Implement parental consent mechanism for children\'s data' }); } // Calculate overall compliance score const totalChecks = 8; const passedChecks = totalChecks - issues.filter(i => i.severity === 'high').length; const complianceScore = (passedChecks / totalChecks) * 100; // Generate recommendations if (complianceScore < 50) { recommendations.push('Urgent: Multiple critical compliance gaps identified. Prioritize immediate remediation.'); } else if (complianceScore < 80) { recommendations.push('Several compliance improvements needed. Create a remediation roadmap.'); } else { recommendations.push('Good compliance posture. Continue monitoring for regulatory updates.'); } return { organizationId: organization.id, assessmentDate: new Date(), complianceScore, issues, recommendations, nextAssessmentDate: this.calculateNextAssessment(complianceScore) }; } private calculateNextAssessment(score: number): Date { const nextDate = new Date(); if (score < 50) { nextDate.setMonth(nextDate.getMonth() + 1); // Monthly if critical issues } else if (score < 80) { nextDate.setMonth(nextDate.getMonth() + 3); // Quarterly if moderate issues } else { nextDate.setMonth(nextDate.getMonth() + 6); // Semi-annually if good } return nextDate; } } interface OrganizationProfile { id: string; name: string; hasDPO: boolean; hasPrivacyPolicy: boolean; privacyPolicyInPortuguese: boolean; hasConsentMechanism: boolean; hasDataSubjectRightsPortal: boolean; hasSecurityMeasures: boolean; hasBreachProcedures: boolean; transfersDataInternationally: boolean; hasInternationalTransferMechanisms: boolean; processesChildrensData: boolean; hasParentalConsentMechanism: boolean; } interface ComplianceIssue { severity: 'high' | 'medium' | 'low'; category: string; issue: string; issuePortuguese: string; article: string; recommendation: string; } interface ComplianceReport { organizationId: string; assessmentDate: Date; complianceScore: number; issues: ComplianceIssue[]; recommendations: string[]; nextAssessmentDate: Date; } ``` ## International Data Transfers Under LGPD LGPD Article 33 governs international data transfers. Here's how to manage them: ```typescript interface InternationalTransferMechanism { id: string; name: string; namePortuguese: string; article: string; requirements: string[]; documentation: string[]; } const lgpdTransferMechanisms: InternationalTransferMechanism[] = [ { id: 'adequacy', name: 'Adequacy Decision', namePortuguese: 'Decisão de Adequação', article: 'Art. 33, I', requirements: [ 'Destination country/organization has adequate data protection', 'ANPD has issued adequacy decision', 'Decision is current and not suspended' ], documentation: [ 'ANPD adequacy list reference', 'Record of adequate jurisdiction' ] }, { id: 'specific_consent', name: 'Specific and Highlighted Consent', namePortuguese: 'Consentimento Específico e Destacado', article: 'Art. 33, VIII', requirements: [ 'Consent specifically for international transfer', 'Clear information about destination', 'Highlighted presentation (not buried in terms)', 'Separate from other consents' ], documentation: [ 'Consent form/screenshot', 'Proof of consent collection', 'Information provided to data subject' ] }, { id: 'standard_clauses', name: 'Standard Contractual Clauses', namePortuguese: 'Cláusulas Contratuais Padrão', article: 'Art. 33, II, b', requirements: [ 'Use ANPD-approved clauses', 'Contract signed by both parties', 'No material modifications to standard clauses', 'Supplementary measures if needed' ], documentation: [ 'Signed SCCs', 'Transfer Impact Assessment', 'Supplementary measures documentation' ] }, { id: 'binding_corporate_rules', name: 'Binding Corporate Rules', namePortuguese: 'Normas Corporativas Globais', article: 'Art. 33, II, c', requirements: [ 'ANPD approval required', 'Binding on all group entities', 'Enforceable data subject rights', 'Clear internal procedures' ], documentation: [ 'BCR document', 'ANPD approval certificate', 'Internal compliance procedures' ] }, { id: 'cooperation_agreement', name: 'International Cooperation Agreement', namePortuguese: 'Acordo de Cooperação Internacional', article: 'Art. 33, IV', requirements: [ 'Between Brazilian and foreign authorities', 'Covers the specific transfer', 'Appropriate safeguards included' ], documentation: [ 'Cooperation agreement reference', 'Scope documentation' ] } ]; class InternationalTransferManager { private transfers: Map = new Map(); assessTransfer(transferDetails: TransferAssessment): TransferDecision { // Check if adequate jurisdiction if (this.isAdequateJurisdiction(transferDetails.destinationCountry)) { return { allowed: true, mechanism: lgpdTransferMechanisms[0], additionalRequirements: [], documentation: ['Record adequate jurisdiction in transfer register'] }; } // Determine best mechanism based on transfer characteristics const recommendedMechanism = this.selectMechanism(transferDetails); if (!recommendedMechanism) { return { allowed: false, mechanism: null, additionalRequirements: ['No valid transfer mechanism available'], documentation: [] }; } return { allowed: true, mechanism: recommendedMechanism, additionalRequirements: this.getAdditionalRequirements(recommendedMechanism, transferDetails), documentation: recommendedMechanism.documentation }; } recordTransfer( transferId: string, details: TransferAssessment, mechanism: InternationalTransferMechanism ): TransferRecord { const record: TransferRecord = { id: transferId, createdAt: new Date(), sourceCountry: 'BR', destinationCountry: details.destinationCountry, destinationOrganization: details.destinationOrganization, dataCategories: details.dataCategories, purposes: details.purposes, mechanism: mechanism.id, legalBasis: details.legalBasis, safeguards: details.safeguards, status: 'active' }; this.transfers.set(transferId, record); return record; } generateTransferRegister(): TransferRegister { const entries = Array.from(this.transfers.values()); return { generatedAt: new Date(), totalTransfers: entries.length, byMechanism: this.groupByMechanism(entries), byDestination: this.groupByDestination(entries), entries: entries.map(e => ({ id: e.id, destination: `${e.destinationOrganization} (${e.destinationCountry})`, mechanism: e.mechanism, dataCategories: e.dataCategories.join(', '), purposes: e.purposes.join(', '), status: e.status })) }; } private isAdequateJurisdiction(country: string): boolean { // As of 2024, ANPD has not yet published adequacy list // When available, check against official list const adequateCountries: string[] = []; // To be updated by ANPD return adequateCountries.includes(country); } private selectMechanism(details: TransferAssessment): InternationalTransferMechanism | null { // Intra-group transfers - recommend BCRs if (details.isIntraGroup && details.hasApprovedBCR) { return lgpdTransferMechanisms.find(m => m.id === 'binding_corporate_rules')!; } // Third-party transfers - recommend SCCs if (!details.isIntraGroup) { return lgpdTransferMechanisms.find(m => m.id === 'standard_clauses')!; } // Consumer-facing - specific consent may work if (details.canObtainSpecificConsent) { return lgpdTransferMechanisms.find(m => m.id === 'specific_consent')!; } return null; } private getAdditionalRequirements( mechanism: InternationalTransferMechanism, details: TransferAssessment ): string[] { const requirements: string[] = []; // High-risk destinations may need supplementary measures if (this.isHighRiskDestination(details.destinationCountry)) { requirements.push('Conduct Transfer Impact Assessment'); requirements.push('Implement supplementary technical measures (encryption, pseudonymization)'); } // Sensitive data requires extra care if (details.includesSensitiveData) { requirements.push('Enhanced security measures for sensitive data'); requirements.push('Specific consent for sensitive data transfer'); } return requirements; } private isHighRiskDestination(country: string): boolean { // Countries without strong data protection laws const highRiskCountries = ['CN', 'RU']; // Example list return highRiskCountries.includes(country); } private groupByMechanism(entries: TransferRecord[]): Record { const groups: Record = {}; for (const entry of entries) { groups[entry.mechanism] = (groups[entry.mechanism] || 0) + 1; } return groups; } private groupByDestination(entries: TransferRecord[]): Record { const groups: Record = {}; for (const entry of entries) { groups[entry.destinationCountry] = (groups[entry.destinationCountry] || 0) + 1; } return groups; } } interface TransferAssessment { destinationCountry: string; destinationOrganization: string; dataCategories: string[]; purposes: string[]; legalBasis: string; safeguards: string[]; isIntraGroup: boolean; hasApprovedBCR: boolean; canObtainSpecificConsent: boolean; includesSensitiveData: boolean; } interface TransferDecision { allowed: boolean; mechanism: InternationalTransferMechanism | null; additionalRequirements: string[]; documentation: string[]; } interface TransferRecord { id: string; createdAt: Date; sourceCountry: string; destinationCountry: string; destinationOrganization: string; dataCategories: string[]; purposes: string[]; mechanism: string; legalBasis: string; safeguards: string[]; status: 'active' | 'suspended' | 'terminated'; } interface TransferRegister { generatedAt: Date; totalTransfers: number; byMechanism: Record; byDestination: Record; entries: Array<{ id: string; destination: string; mechanism: string; dataCategories: string; purposes: string; status: string; }>; } ``` ## FAQ ### Does LGPD apply to my business if I'm not based in Brazil? Yes, if you: (1) process personal data of individuals in Brazil, (2) offer goods or services to the Brazilian market, or (3) collect data in Brazil regardless of processing location. The territorial scope is similar to GDPR's. ### How does LGPD define "children" differently from GDPR? LGPD considers anyone under 18 as a child, requiring parental consent for all processing. GDPR typically sets the threshold at 16 (with member state flexibility down to 13). This is a significant difference for businesses operating in both regions. ### What is the "Credit Protection" legal basis unique to LGPD? Article 7, X allows processing for "credit protection purposes." This is unique to LGPD and reflects Brazil's established credit bureau system. It covers credit scoring, risk assessment, and financial data sharing for credit decisions, subject to Consumer Code protections. ### How quickly must I notify the ANPD of a data breach? LGPD requires notification within a "reasonable time" rather than GDPR's strict 72 hours. However, the ANPD has indicated they expect notification within 2 business days for serious incidents. Err on the side of faster notification. ### Do I need a DPO even for a small business? LGPD requires a DPO for all data controllers, unlike GDPR which has exceptions. However, the ANPD has issued guidelines allowing small businesses and startups to simplify compliance, potentially using outsourced DPO services or designating an internal employee with other duties. ## Getting Started with LGPD Compliance LGPD compliance is not just about avoiding fines—it's about building trust with Brazilian consumers in one of the world's largest digital markets. Here's your action plan: 1. **Conduct a data mapping exercise** to understand what Brazilian personal data you process 2. **Identify your legal bases** for each processing activity using the 10-basis framework 3. **Appoint a DPO** (Encarregado) and publish their contact information 4. **Implement a Portuguese-language consent mechanism** for your website and apps 5. **Create a data subject rights portal** to handle access, deletion, and portability requests 6. **Review international transfers** and ensure appropriate mechanisms are in place 7. **Train your team** on LGPD requirements and their specific responsibilities 8. **Document everything** - LGPD requires demonstrable compliance By following this guide and implementing the provided code examples, you'll be well on your way to LGPD compliance while building stronger relationships with your Brazilian users.

Domande frequenti

Does LGPD apply to foreign companies?
Yes. LGPD applies to any company, regardless of where it is headquartered, if it processes data of individuals located in Brazil or offers goods/services to the Brazilian market.
Is a DPO required under LGPD?
Yes, generally all data controllers must appoint a Data Protection Officer (Encarregado), though the national authority (ANPD) has waived this requirement for certain small businesses and startups.
R

Rachel Torres, Privacy Counsel

Autore presso GetCookies, specializzato in conformità privacy, gestione del consenso e ottimizzazione del marketing digitale.

Pronto a semplificare il consenso cookie?

GetCookies rende la conformità GDPR, CCPA e privacy globale senza sforzo. Inizia oggi.