Code beginner · 3 min read

How to extract entities from text with Python

Direct answer
Use the OpenAI Python SDK to send a prompt that instructs the model to extract entities from text, then parse the structured response from chat.completions.create.

Setup

Install
bash
pip install openai
Env vars
OPENAI_API_KEY
Imports
python
import os
from openai import OpenAI
import json

Examples

inApple was founded by Steve Jobs and Steve Wozniak in California.
out[{"entity": "Apple", "type": "Organization"}, {"entity": "Steve Jobs", "type": "Person"}, {"entity": "Steve Wozniak", "type": "Person"}, {"entity": "California", "type": "Location"}]
inAmazon's headquarters are in Seattle, and Jeff Bezos founded it in 1994.
out[{"entity": "Amazon", "type": "Organization"}, {"entity": "Seattle", "type": "Location"}, {"entity": "Jeff Bezos", "type": "Person"}, {"entity": "1994", "type": "Date"}]
inNo entities here, just plain text.
out[]

Integration steps

  1. Install the OpenAI Python SDK and set the OPENAI_API_KEY environment variable.
  2. Import OpenAI and initialize the client with the API key from os.environ.
  3. Create a prompt instructing the model to extract entities and their types from the input text.
  4. Call client.chat.completions.create with a suitable model and the prompt message.
  5. Parse the JSON-formatted string response to extract entities as a list of dictionaries.

Full code

python
import os
from openai import OpenAI
import json

client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])

def extract_entities(text: str):
    prompt = (
        f"Extract all named entities from the following text as a JSON list of objects with 'entity' and 'type' keys.\n"
        f"Text: {text}\n"
        f"Output format example: [{'{"entity": "Apple", "type": "Organization"}'}]"
    )

    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": prompt}]
    )

    content = response.choices[0].message.content
    try:
        entities = json.loads(content)
    except json.JSONDecodeError:
        entities = []  # fallback if parsing fails
    return entities

if __name__ == "__main__":
    sample_text = "Apple was founded by Steve Jobs and Steve Wozniak in California."
    extracted = extract_entities(sample_text)
    print("Extracted entities:")
    for entity in extracted:
        print(f"- {entity['entity']} ({entity['type']})")
output
Extracted entities:
- Apple (Organization)
- Steve Jobs (Person)
- Steve Wozniak (Person)
- California (Location)

API trace

Request
json
{"model": "gpt-4o-mini", "messages": [{"role": "user", "content": "Extract all named entities from the following text as a JSON list of objects with 'entity' and 'type' keys.\nText: Apple was founded by Steve Jobs and Steve Wozniak in California.\nOutput format example: [{\"entity\": \"Apple\", \"type\": \"Organization\"}]"}]}
Response
json
{"choices": [{"message": {"content": "[{\"entity\": \"Apple\", \"type\": \"Organization\"}, {\"entity\": \"Steve Jobs\", \"type\": \"Person\"}, {\"entity\": \"Steve Wozniak\", \"type\": \"Person\"}, {\"entity\": \"California\", \"type\": \"Location\"}]"}}]}
Extractresponse.choices[0].message.content

Variants

Streaming entity extraction ›

Use streaming when extracting entities from longer texts to start processing partial results earlier and improve user experience.

python
import os
from openai import OpenAI
import json

client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])

def extract_entities_stream(text: str):
    prompt = (
        f"Extract all named entities from the following text as a JSON list of objects with 'entity' and 'type' keys.\n"
        f"Text: {text}\n"
        f"Output format example: [{'{"entity": "Apple", "type": "Organization"}'}]"
    )

    stream = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": prompt}],
        stream=True
    )

    full_response = ""
    for chunk in stream:
        delta = chunk.choices[0].delta.content or ""
        full_response += delta
    try:
        entities = json.loads(full_response)
    except json.JSONDecodeError:
        entities = []
    return entities

if __name__ == "__main__":
    sample_text = "Amazon's headquarters are in Seattle, and Jeff Bezos founded it in 1994."
    extracted = extract_entities_stream(sample_text)
    print("Extracted entities:")
    for entity in extracted:
        print(f"- {entity['entity']} ({entity['type']})")
Async entity extraction ›

Use async version for concurrent entity extraction calls in applications requiring high throughput or responsiveness.

python
import os
import asyncio
from openai import OpenAI
import json

client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])

async def extract_entities_async(text: str):
    prompt = (
        f"Extract all named entities from the following text as a JSON list of objects with 'entity' and 'type' keys.\n"
        f"Text: {text}\n"
        f"Output format example: [{'{"entity": "Apple", "type": "Organization"}'}]"
    )

    response = await client.chat.completions.acreate(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": prompt}]
    )

    content = response.choices[0].message.content
    try:
        entities = json.loads(content)
    except json.JSONDecodeError:
        entities = []
    return entities

async def main():
    sample_text = "No entities here, just plain text."
    extracted = await extract_entities_async(sample_text)
    print("Extracted entities:")
    for entity in extracted:
        print(f"- {entity['entity']} ({entity['type']})")

if __name__ == "__main__":
    asyncio.run(main())
Use Anthropic Claude for entity extraction ›

Use Anthropic Claude models if you prefer Claude's style or want an alternative to OpenAI for entity extraction.

python
import os
from anthropic import Anthropic
import json

client = Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])

def extract_entities_claude(text: str):
    system_prompt = "You are a helpful assistant that extracts named entities as JSON objects with 'entity' and 'type'."
    user_message = f"Extract entities from this text:\n{text}"

    response = client.messages.create(
        model="claude-3-5-sonnet-20241022",
        max_tokens=1024,
        system=system_prompt,
        messages=[{"role": "user", "content": user_message}]
    )

    content = response.content[0].text
    try:
        entities = json.loads(content)
    except json.JSONDecodeError:
        entities = []
    return entities

if __name__ == "__main__":
    sample_text = "Google was founded by Larry Page and Sergey Brin."
    extracted = extract_entities_claude(sample_text)
    print("Extracted entities:")
    for entity in extracted:
        print(f"- {entity['entity']} ({entity['type']})")

Performance

Latency~800ms for gpt-4o-mini non-streaming calls
Cost~$0.0015 per 500 tokens for gpt-4o-mini
Rate limitsTier 1: 500 requests per minute / 30,000 tokens per minute
  • Keep prompts concise and focused on entity extraction only.
  • Use smaller models like gpt-4o-mini for faster, cheaper extraction on short texts.
  • Batch multiple texts in one prompt if possible to reduce overhead.
ApproachLatencyCost/callBest for
Standard OpenAI chat completion~800ms~$0.0015Simple, synchronous extraction
Streaming OpenAI chat completion~800ms + streaming~$0.0015Long texts with progressive output
Async OpenAI chat completion~800ms~$0.0015Concurrent extraction in async apps
Anthropic Claude chat completion~900msCheck Anthropic pricingAlternative model with different style
✓

Quick tip

Always instruct the model to output entities in a strict JSON format to simplify parsing and downstream processing.

⚠

Common mistake

Beginners often forget to parse the model's text response as JSON, leading to errors when extracting entities.

Verified 2026-04 · gpt-4o-mini, claude-3-5-sonnet-20241022
Verify ↗

Community Notes

No notes yetBe the first to share a version-specific fix or tip.