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        else:
158            print(
159                "No downloadable formats available for the first document or document identifier missing."
160            )
161    else:
162        print("No documents listed for this application.")
163
164    # Download publication XML (grant or pgpub)
165    print("\nChecking for publication files (grant/pgpub XML)...")
166    if patent_wrapper_detail.grant_document_meta_data:
167        grant_metadata = patent_wrapper_detail.grant_document_meta_data
168        print(f"Grant document available: {grant_metadata.xml_file_name}")
169        print(f"  Product: {grant_metadata.product_identifier}")
170        print(f"  Created: {grant_metadata.file_create_date_time}")
171
172        print("\nDownloading grant XML...")
173        grant_path = client.download_publication(
174            printed_metadata=grant_metadata,
175            destination=DEST_PATH,
176            overwrite=True,
177        )
178        print(f"Downloaded grant XML to: {grant_path}")
179
180    if patent_wrapper_detail.pgpub_document_meta_data:
181        pgpub_metadata = patent_wrapper_detail.pgpub_document_meta_data
182        print(f"\nPre-grant publication available: {pgpub_metadata.xml_file_name}")
183
184        pgpub_path = client.download_publication(
185            printed_metadata=pgpub_metadata,
186            file_name="my_pgpub.xml",
187            destination=DEST_PATH,
188            overwrite=True,
189        )
190        print(f"Downloaded pgpub XML to: {pgpub_path}")
191
192    if patent_wrapper_detail.assignment_bag:
193        print("\nAssignments:")
194        for assignment in patent_wrapper_detail.assignment_bag:
195            for assignee in assignment.assignee_bag:
196                print(
197                    f"  - {assignee.assignee_name_text} (Recorded: {assignment.assignment_recorded_date})"
198                )
199                print(f"    Conveyance: {assignment.conveyance_text}")
200else:
201    print(f"Could not retrieve details for application {app_no_to_fetch}")
202
203print("-" * 40)
204print("Example 5: Search by patent number")
205print("-" * 40)
206
207target_patent_number = "10000000"
208print(f"Searching for patent US {target_patent_number} B2...")
209patent_search_response = client.search_applications(
210    patent_number_q=target_patent_number, limit=1
211)
212
213if (
214    patent_search_response.count > 0
215    and patent_search_response.patent_file_wrapper_data_bag
216):
217    found_patent_wrapper = patent_search_response.patent_file_wrapper_data_bag[0]
218    if (
219        found_patent_wrapper.application_meta_data
220        and found_patent_wrapper.application_meta_data.patent_number
221    ):
222        print(
223            f"Retrieved patent: US {found_patent_wrapper.application_meta_data.patent_number}"
224        )
225    else:
226        print(
227            f"Retrieved patent application: {found_patent_wrapper.application_number_text}"
228        )
229
230    if found_patent_wrapper.patent_term_adjustment_data:
231        pta = found_patent_wrapper.patent_term_adjustment_data
232        print(f"Patent Term Adjustment: {pta.adjustment_total_quantity} days")
233        if pta.a_delay_quantity is not None:
234            print(f"  A Delay: {pta.a_delay_quantity} days")
235        if pta.b_delay_quantity is not None:
236            print(f"  B Delay: {pta.b_delay_quantity} days")
237        if pta.c_delay_quantity is not None:
238            print(f"  C Delay: {pta.c_delay_quantity} days")
239        if pta.applicant_day_delay_quantity is not None:
240            print(f"  Applicant Delay: {pta.applicant_day_delay_quantity} days")
241
242    continuity_data = ApplicationContinuityData.from_wrapper(
243        wrapper=found_patent_wrapper
244    )
245    if continuity_data.parent_continuity_bag:
246        print("\nParent Applications:")
247        for p_continuity in continuity_data.parent_continuity_bag:
248            print(f"  - App No: {p_continuity.parent_application_number_text}")
249            print(
250                f"    Type: {p_continuity.claim_parentage_type_code_description_text}"
251            )
252            print(f"    Filing Date: {p_continuity.parent_application_filing_date}")
253
254    if continuity_data.child_continuity_bag:
255        print("\nChild Applications:")
256        for c_continuity in continuity_data.child_continuity_bag:
257            print(f"  - App No: {c_continuity.child_application_number_text}")
258            print(
259                f"    Type: {c_continuity.claim_parentage_type_code_description_text}"
260            )
261            print(f"    Filing Date: {c_continuity.child_application_filing_date}")
262else:
263    print(f"No patents found with patent number: {target_patent_number}")
264
265print("-" * 40)
266print("Example 6: POST search")
267print("-" * 40)
268
269print("POST search for applications with 'AI' in title...")
270post_search_body = {
271    "q": "applicationMetaData.inventionTitle:AI",
272    "pagination": {"offset": 0, "limit": 2},
273}
274post_response = client.search_applications(post_body=post_search_body)
275print(
276    f"Found {post_response.count} applications via POST search (showing up to 2)."
277)
278for patent_wrapper in post_response.patent_file_wrapper_data_bag:
279    if patent_wrapper.application_meta_data:
280        print(
281            f"  - App No: {patent_wrapper.application_number_text}, Title: {patent_wrapper.application_meta_data.invention_title}"
282        )
283
284print("-" * 40)
285print("Example 7: Search by CPC classification")
286print("-" * 40)
287
288# CPC codes containing spaces or slashes are automatically quoted for the Lucene query.
289print("Searching by CPC classification code 'H10D  64/667'...")
290cpc_response = client.search_applications(classification_q="H10D  64/667", limit=3)
291print(f"Found {cpc_response.count} applications with CPC code H10D 64/667.")
292for patent_wrapper in cpc_response.patent_file_wrapper_data_bag:
293    app_meta = patent_wrapper.application_meta_data
294    if app_meta:
295        print(
296            f"  - App No: {patent_wrapper.application_number_text}, Title: {app_meta.invention_title}"
297        )
298        if app_meta.cpc_classification_bag:
299            print(f"    CPC codes: {', '.join(app_meta.cpc_classification_bag)}")
300
301print("-" * 40)
302print("Example 8: Get status codes")
303print("-" * 40)
304
305status_code_response = client.get_status_codes(params={"limit": 5})
306print(
307    f"Retrieved {len(status_code_response.status_code_bag)} status codes (out of {status_code_response.count} total)."
308)
309for code_obj in status_code_response.status_code_bag:
310    print(f"  - Code: {code_obj.code}, Description: {code_obj.description}")