Patent Data Examples

  1"""Example usage of pyUSPTO for patent application search and retrieval.
  2
  3Demonstrates the PatentDataClient for searching applications, retrieving metadata,
  4downloading documents, and exporting CSV.
  5"""
  6
  7import json
  8import os
  9
 10from pyUSPTO import ApplicationContinuityData, PatentDataClient, USPTOConfig
 11
 12DEST_PATH = "./notes/download-example"
 13
 14# --- Client Initialization ---
 15api_key = os.environ.get("USPTO_API_KEY", "YOUR_API_KEY_HERE")
 16if api_key == "YOUR_API_KEY_HERE":
 17    raise ValueError(
 18        "API key is not set. Set the USPTO_API_KEY environment variable."
 19    )
 20config = USPTOConfig(api_key=api_key)
 21client = PatentDataClient(config=config)
 22
 23print("-" * 40)
 24print("Example 1: Default search")
 25print("-" * 40)
 26
 27response = client.search_applications(limit=5)
 28print(
 29    f"Found {response.count} total patent applications matching default/broad criteria."
 30)
 31print(
 32    f"Displaying first {len(response.patent_file_wrapper_data_bag)} applications from response:"
 33)
 34
 35for patent_wrapper in response.patent_file_wrapper_data_bag:
 36    app_meta = patent_wrapper.application_meta_data
 37    if app_meta:
 38        print(f"\n  Application: {patent_wrapper.application_number_text}")
 39        print(f"  Title: {app_meta.invention_title}")
 40        print(f"  Status: {app_meta.application_status_description_text}")
 41        print(f"  Filing Date: {app_meta.filing_date}")
 42
 43        if app_meta.patent_number:
 44            print(f"  Patent Number: {app_meta.patent_number}")
 45            print(f"  Grant Date: {app_meta.grant_date}")
 46
 47        if app_meta.inventor_bag:
 48            print("  Inventors:")
 49            for inventor in app_meta.inventor_bag:
 50                name_parts = [
 51                    part
 52                    for part in [inventor.first_name, inventor.last_name]
 53                    if part
 54                ]
 55                print(f"    - {' '.join(name_parts).strip()}")
 56                if inventor.correspondence_address_bag:
 57                    address = inventor.correspondence_address_bag[0]
 58                    if address.city_name and address.geographic_region_code:
 59                        print(
 60                            f"      ({address.city_name}, {address.geographic_region_code})"
 61                        )
 62
 63        if app_meta.applicant_bag:
 64            print("  Applicants:")
 65            for applicant in app_meta.applicant_bag:
 66                print(f"    - {applicant.applicant_name_text}")
 67
 68# Export results to CSV
 69if response.count > 0:
 70    print("\nGenerating CSV for the current response:")
 71    csv_data = response.to_csv()
 72    csv_path = os.path.join(DEST_PATH, "patent_search_results.csv")
 73    os.makedirs(DEST_PATH, exist_ok=True)
 74    with open(csv_path, "w", newline="", encoding="utf-8") as f:
 75        f.write(csv_data)
 76        print(f"Full CSV data saved to {csv_path}.")
 77
 78print("-" * 40)
 79print("Example 2: Search by inventor name")
 80print("-" * 40)
 81
 82inventor_search_response = client.search_applications(
 83    inventor_name_q="Smith", limit=2
 84)
 85print(
 86    f"Found {inventor_search_response.count} patents with 'Smith' as inventor (showing up to 2)."
 87)
 88for patent_wrapper in inventor_search_response.patent_file_wrapper_data_bag:
 89    if patent_wrapper.application_meta_data:
 90        print(
 91            f"  - App No: {patent_wrapper.application_number_text}, Title: {patent_wrapper.application_meta_data.invention_title}"
 92        )
 93
 94print("-" * 40)
 95print("Example 3: Search by filing date range")
 96print("-" * 40)
 97
 98date_search_response = client.search_applications(
 99    filing_date_from_q="2020-01-01", filing_date_to_q="2020-12-31", limit=2
100)
101print(
102    f"Found {date_search_response.count} patents filed in 2020 (showing up to 2)."
103)
104for patent_wrapper in date_search_response.patent_file_wrapper_data_bag:
105    if patent_wrapper.application_meta_data:
106        print(
107            f"  - App No: {patent_wrapper.application_number_text}, Filing Date: {patent_wrapper.application_meta_data.filing_date}"
108        )
109
110print("-" * 40)
111print("Example 4: Get application by number")
112print("-" * 40)
113
114app_no_to_fetch = "18045436"
115print(f"Retrieving patent application: {app_no_to_fetch}")
116patent_wrapper_detail = client.get_application_by_number(
117    application_number=app_no_to_fetch
118)
119if patent_wrapper_detail:
120    print(
121        f"Successfully retrieved: {patent_wrapper_detail.application_number_text}"
122    )
123    if patent_wrapper_detail.application_meta_data:
124        print(
125            f"Title: {patent_wrapper_detail.application_meta_data.invention_title}"
126        )
127
128    print("\nRetrieving document information...")
129    documents_bag = client.get_application_documents(
130        application_number=app_no_to_fetch
131    )
132    print(f"Found {len(documents_bag)} documents for application {app_no_to_fetch}")
133
134    if documents_bag.documents:
135        document_to_download = documents_bag.documents[0]
136        print("\nFirst document details:")
137        print(f"  Document ID: {document_to_download.document_identifier}")
138        print(
139            f"  Document Type: {document_to_download.document_code} - {document_to_download.document_code_description_text}"
140        )
141        print(f"  Date: {document_to_download.official_date}")
142        print(f"  Direction: {document_to_download.direction_category}")
143
144        if (
145            document_to_download.document_formats
146            and document_to_download.document_identifier
147        ):
148            print("\nDownloading first PDF document...")
149            print(json.dumps(document_to_download.to_dict(), indent=2))
150            downloaded_path = client.download_document(
151                document=document_to_download,
152                format="PDF",
153                destination=DEST_PATH,
154                overwrite=True,
155            )
156            print(f"Downloaded document to: {downloaded_path}")
157
158            print("\nStreaming same document to memory...")
159            with client.stream_document(
160                document=document_to_download, format="PDF"
161            ) as response:
162                content = response.content
163                print(f"Streamed {len(content)} bytes")
164        else:
165            print(
166                "No downloadable formats available for the first document or document identifier missing."
167            )
168    else:
169        print("No documents listed for this application.")
170
171    # Download publication XML (grant or pgpub)
172    print("\nChecking for publication files (grant/pgpub XML)...")
173    if patent_wrapper_detail.grant_document_meta_data:
174        grant_metadata = patent_wrapper_detail.grant_document_meta_data
175        print(f"Grant document available: {grant_metadata.xml_file_name}")
176        print(f"  Product: {grant_metadata.product_identifier}")
177        print(f"  Created: {grant_metadata.file_create_date_time}")
178
179        print("\nDownloading grant XML...")
180        grant_path = client.download_publication(
181            printed_metadata=grant_metadata,
182            destination=DEST_PATH,
183            overwrite=True,
184        )
185        print(f"Downloaded grant XML to: {grant_path}")
186
187    if patent_wrapper_detail.pgpub_document_meta_data:
188        pgpub_metadata = patent_wrapper_detail.pgpub_document_meta_data
189        print(f"\nPre-grant publication available: {pgpub_metadata.xml_file_name}")
190
191        pgpub_path = client.download_publication(
192            printed_metadata=pgpub_metadata,
193            file_name="my_pgpub.xml",
194            destination=DEST_PATH,
195            overwrite=True,
196        )
197        print(f"Downloaded pgpub XML to: {pgpub_path}")
198
199    if patent_wrapper_detail.assignment_bag:
200        print("\nAssignments:")
201        for assignment in patent_wrapper_detail.assignment_bag:
202            for assignee in assignment.assignee_bag:
203                print(
204                    f"  - {assignee.assignee_name_text} (Recorded: {assignment.assignment_recorded_date})"
205                )
206                print(f"    Conveyance: {assignment.conveyance_text}")
207else:
208    print(f"Could not retrieve details for application {app_no_to_fetch}")
209
210print("-" * 40)
211print("Example 5: Search by patent number")
212print("-" * 40)
213
214target_patent_number = "10000000"
215print(f"Searching for patent US {target_patent_number} B2...")
216patent_search_response = client.search_applications(
217    patent_number_q=target_patent_number, limit=1
218)
219
220if (
221    patent_search_response.count > 0
222    and patent_search_response.patent_file_wrapper_data_bag
223):
224    found_patent_wrapper = patent_search_response.patent_file_wrapper_data_bag[0]
225    if (
226        found_patent_wrapper.application_meta_data
227        and found_patent_wrapper.application_meta_data.patent_number
228    ):
229        print(
230            f"Retrieved patent: US {found_patent_wrapper.application_meta_data.patent_number}"
231        )
232    else:
233        print(
234            f"Retrieved patent application: {found_patent_wrapper.application_number_text}"
235        )
236
237    if found_patent_wrapper.patent_term_adjustment_data:
238        pta = found_patent_wrapper.patent_term_adjustment_data
239        print(f"Patent Term Adjustment: {pta.adjustment_total_quantity} days")
240        if pta.a_delay_quantity is not None:
241            print(f"  A Delay: {pta.a_delay_quantity} days")
242        if pta.b_delay_quantity is not None:
243            print(f"  B Delay: {pta.b_delay_quantity} days")
244        if pta.c_delay_quantity is not None:
245            print(f"  C Delay: {pta.c_delay_quantity} days")
246        if pta.applicant_day_delay_quantity is not None:
247            print(f"  Applicant Delay: {pta.applicant_day_delay_quantity} days")
248
249    continuity_data = ApplicationContinuityData.from_wrapper(
250        wrapper=found_patent_wrapper
251    )
252    if continuity_data.parent_continuity_bag:
253        print("\nParent Applications:")
254        for p_continuity in continuity_data.parent_continuity_bag:
255            print(f"  - App No: {p_continuity.parent_application_number_text}")
256            print(
257                f"    Type: {p_continuity.claim_parentage_type_code_description_text}"
258            )
259            print(f"    Filing Date: {p_continuity.parent_application_filing_date}")
260
261    if continuity_data.child_continuity_bag:
262        print("\nChild Applications:")
263        for c_continuity in continuity_data.child_continuity_bag:
264            print(f"  - App No: {c_continuity.child_application_number_text}")
265            print(
266                f"    Type: {c_continuity.claim_parentage_type_code_description_text}"
267            )
268            print(f"    Filing Date: {c_continuity.child_application_filing_date}")
269else:
270    print(f"No patents found with patent number: {target_patent_number}")
271
272print("-" * 40)
273print("Example 6: POST search")
274print("-" * 40)
275
276print("POST search for applications with 'AI' in title...")
277post_search_body = {
278    "q": "applicationMetaData.inventionTitle:AI",
279    "pagination": {"offset": 0, "limit": 2},
280}
281post_response = client.search_applications(post_body=post_search_body)
282print(
283    f"Found {post_response.count} applications via POST search (showing up to 2)."
284)
285for patent_wrapper in post_response.patent_file_wrapper_data_bag:
286    if patent_wrapper.application_meta_data:
287        print(
288            f"  - App No: {patent_wrapper.application_number_text}, Title: {patent_wrapper.application_meta_data.invention_title}"
289        )
290
291print("-" * 40)
292print("Example 7: Search by CPC classification")
293print("-" * 40)
294
295# CPC codes containing spaces or slashes are automatically quoted for the Lucene query.
296print("Searching by CPC classification code 'H10D  64/667'...")
297cpc_response = client.search_applications(classification_q="H10D  64/667", limit=3)
298print(f"Found {cpc_response.count} applications with CPC code H10D 64/667.")
299for patent_wrapper in cpc_response.patent_file_wrapper_data_bag:
300    app_meta = patent_wrapper.application_meta_data
301    if app_meta:
302        print(
303            f"  - App No: {patent_wrapper.application_number_text}, Title: {app_meta.invention_title}"
304        )
305        if app_meta.cpc_classification_bag:
306            print(f"    CPC codes: {', '.join(app_meta.cpc_classification_bag)}")
307
308print("-" * 40)
309print("Example 8: Get status codes")
310print("-" * 40)
311
312status_code_response = client.get_status_codes(params={"limit": 5})
313print(
314    f"Retrieved {len(status_code_response.status_code_bag)} status codes (out of {status_code_response.count} total)."
315)
316for code_obj in status_code_response.status_code_bag:
317    print(f"  - Code: {code_obj.code}, Description: {code_obj.description}")