{T}

Web服务API

百度地图Web服务API为开发者提供HTTP接口,可在服务端调用,实现地点检索、路线规划、地理编码等功能。

基础说明

接口地址

code
https://api.map.baidu.com/

请求方式

支持GET和POST请求,返回JSON或XML格式数据。

公共参数

参数名必填说明
ak用户密钥
output输出格式,默认JSON
callbackJSONP回调函数名
sn安全签名
timestamp时间戳(SN签名时需要)

响应格式

json
{
  "status": 0,
  "message": "ok",
  "result": {}
}

错误码大全

状态码说明解决方案
0成功-
1服务器内部错误重试或联系技术支持
2参数无效检查参数格式和必填项
3权限不足检查AK配置和权限
4配额超限升级配额或购买配额包
5AK不存在检查AK是否正确
6IP或域名未授权配置白名单
7SN签名错误检查签名算法和SK
8请求过于频繁降低请求频率,使用缓存
9服务不可用稍后重试
10API不存在检查接口地址
11请求方法错误使用正确的HTTP方法
12请求超时优化请求内容,减少数据量
13数据格式错误检查JSON/XML格式
14服务正在维护等待维护完成
15功能未开通联系商务开通功能
16坐标无效检查坐标格式和范围
17地址解析失败使用更准确的地址
18路线规划失败检查起终点是否可达
19搜索无结果调整搜索关键词
20超时增加超时时间
21坐标转换失败检查原始坐标
22行政区不存在检查行政区名称
23天气查询失败检查城市名称
24实时路况不可用稍后重试
25轨迹服务异常检查entity_name等参数
101AK参数缺失添加ak参数
102AK不合法检查AK格式
103AK已被禁用联系客服处理
200服务内部错误联系技术支持
201服务在当前区域不可用检查服务范围
202服务在当前时间不可用等待服务恢复
300未知错误联系技术支持

配额与限流

免费配额

服务类型日配额QPS限制单次返回
地点检索5,000次5020条
地点详情5,000次50-
地理编码5,000次50-
逆地理编码5,000次50-
路线规划5,000次50-
坐标转换5,000次50100点
静态图5,000次50-
行政区域5,000次50-

配额提升

方式配额提升费用
企业认证2-5倍免费
配额包自定义按量计费
商务定制不限协商定价

限流策略

javascript
// 实现请求限流
class RateLimiter {
  constructor(qps = 50) {
    this.qps = qps;
    this.queue = [];
    this.lastTime = 0;
  }

  async request(url) {
    const now = Date.now();
    const elapsed = now - this.lastTime;
    const minInterval = 1000 / this.qps;

    if (elapsed < minInterval) {
      await new Promise(resolve => setTimeout(resolve, minInterval - elapsed));
    }

    this.lastTime = Date.now();
    return fetch(url);
  }
}

const limiter = new RateLimiter(50);

地点检索

地点搜索

http
GET https://api.map.baidu.com/place/v2/search?query=餐厅&region=北京&output=json&ak=您的密钥
参数必填类型说明
queryString检索关键字,多个用$分隔
regionString检索区域(城市名)
city_limitBoolean是否限制在区域内
outputString输出格式
page_numNumber分页页码,默认0
page_sizeNumber分页大小,默认10,最大20
scopeNumber检索精度:1基础,2详细
filterString过滤条件
coord_typeNumber坐标类型:1WGS84,2GCJ02,3BD09

响应示例:

json
{
  "status": 0,
  "message": "ok",
  "total": 100,
  "results": [
    {
      "name": "餐厅名称",
      "location": {
        "lng": 116.404,
        "lat": 39.915
      },
      "address": "详细地址",
      "province": "北京市",
      "city": "北京市",
      "area": "海淀区",
      "telephone": "电话号码",
      "uid": "唯一标识",
      "street_id": "街道ID",
      "detail": 1,
      "detail_info": {
        "tag": "标签",
        "rating": 4.5,
        "price": 80,
        "shop_hours": "营业时间"
      }
    }
  ]
}

周边搜索

http
GET https://api.map.baidu.com/place/v2/search?query=餐厅&location=39.915,116.404&radius=1000&output=json&ak=您的密钥
参数必填类型说明
queryString检索关键字
locationString中心点坐标(纬度,经度)
radiusNumber搜索半径,默认1000米
radius_limitBoolean是否严格限制半径
sort_by_distanceNumber按距离排序:0否,1是
filterString过滤条件

多边形区域搜索

http
GET https://api.map.baidu.com/place/v2/search?query=餐厅&bounds=39.915,116.404,39.975,116.414&output=json&ak=您的密钥
参数说明
bounds区域范围:左下角纬度,左下角经度,右上角纬度,右上角经度

地点详情

http
GET https://api.map.baidu.com/place/v2/detail?uid=地点UID&output=json&ak=您的密钥

响应示例:

json
{
  "status": 0,
  "result": {
    "uid": "xxx",
    "name": "地点名称",
    "location": {"lng": 116.404, "lat": 39.915},
    "address": "详细地址",
    "telephone": "电话",
    "detail_info": {
      "tag": "分类标签",
      "rating": 4.5,
      "price": 80,
      "shop_hours": "营业时间",
      "alias": "别名",
      "description": "描述",
      "image": "图片URL",
      "photos": ["图片数组"],
      "scope_type": "类型",
      "scope_grade": "等级",
      "content_tag": "内容标签"
    }
  }
}

地点输入提示

http
GET https://api.map.baidu.com/place/v2/suggestion?query=中关村&region=北京&output=json&ak=您的密钥

响应示例:

json
{
  "status": 0,
  "result": [
    {
      "name": "中关村",
      "location": {"lng": 116.31, "lat": 39.98},
      "uid": "xxx",
      "city": "北京市",
      "district": "海淀区",
      "business": "中关村"
    }
  ]
}

地理编码

地理编码(地址转坐标)

http
GET https://api.map.baidu.com/geocoding/v3/?address=北京市海淀区上地十街10号&output=json&ak=您的密钥
参数必填类型说明
addressString待解析的地址
cityString指定城市
ret_coordtypeString返回坐标类型:bd09ll/gcj02ll/wgs84ll
postal_codeNumber是否返回邮编:0否,1是

响应示例:

json
{
  "status": 0,
  "result": {
    "location": {
      "lng": 116.308,
      "lat": 40.056
    },
    "precise": 1,
    "confidence": 80,
    "comprehension": 100,
    "level": "道路"
  }
}
字段说明
precise精确程度:1精确,0模糊
confidence置信度(0-100)
comprehension理解程度(0-100)
level地址级别:道路、道路交叉口、POI等

逆地理编码(坐标转地址)

http
GET https://api.map.baidu.com/reverse_geocoding/v3/?location=40.056,116.308&output=json&ak=您的密钥
参数必填类型说明
locationString坐标(纬度,经度)
coordtypeString坐标类型:bd09ll/gcj02ll/wgs84ll
radiusNumberPOI召回半径,默认1000
extensions_poiString是否返回POI:road/road surrounding/poi
extensions_roadBoolean是否返回道路信息
extensions_townBoolean是否返回乡镇信息
languageString语言:zh-CN/en-GB

响应示例:

json
{
  "status": 0,
  "result": {
    "location": {
      "lng": 116.308,
      "lat": 40.056
    },
    "formatted_address": "北京市海淀区上地十街10号",
    "business": "上地",
    "addressComponent": {
      "country": "中国",
      "country_code": 0,
      "country_code_iso": "CHN",
      "country_code_iso2": "CN",
      "province": "北京市",
      "city": "北京市",
      "city_level": 2,
      "district": "海淀区",
      "town": "上地街道",
      "adcode": "110108",
      "street": "上地十街",
      "street_number": "10号",
      "direction": "附近",
      "distance": "10"
    },
    "pois": [
      {
        "addr": "详细地址",
        "cp": "数据来源",
        "direction": "方向",
        "distance": "距离",
        "name": "POI名称",
        "poiType": "POI类型",
        "point": {"x": 116.308, "y": 40.056},
        "tag": "标签",
        "tel": "电话",
        "uid": "唯一标识",
        "zip": "邮编"
      }
    ],
    "roads": [],
    "poiRegions": []
  }
}

路线规划

驾车路线规划

http
GET https://api.map.baidu.com/direction/v2/driving?origin=40.056,116.308&destination=39.915,116.404&output=json&ak=您的密钥
参数必填类型说明
originString起点(纬度,经度)
destinationString终点(纬度,经度)
waypointsString途经点,多个用|分隔
tacticsNumber导航策略
coord_typeString坐标类型
alternativesBoolean是否返回备选路线
speed_limitNumber限速(KM/h)
avoid_roadsString避让道路名称
avoid_scenesNumber避让场景

导航策略:

说明
0默认
1逃避拥堵
2距离优先(距离最短)
3不走高速
4躲避收费
5躲避收费&不走高速
6躲避收费&躲避拥堵
7躲避收费&不走高速&躲避拥堵
8优先高速
9躲避拥堵&优先高速
10躲避收费&躲避拥堵&优先高速
11优先大道
12优先大道&躲避拥堵

响应示例:

json
{
  "status": 0,
  "result": {
    "routes": [
      {
        "distance": 12000,
        "duration": 1800,
        "toll": 10,
        "toll_distance": 5000,
        "toll_info": {"toll_price": 10, "toll_mileage": 5},
        "restriction": 0,
        "traffic_lights": 15,
        "steps": [
          {
            "distance": 500,
            "duration": 60,
            "road": "道路名称",
            "instruction": "沿道路名称行驶500米",
            "path": "坐标串",
            "start_location": {"lng": 116.308, "lat": 40.056},
            "end_location": {"lng": 116.310, "lat": 40.060},
            "turn_type": "直行",
            "road_type": 0,
            "direction": "东",
            "traffic_condition": [
              {"distance": 300, "status": 1},
              {"distance": 200, "status": 2}
            ]
          }
        ]
      }
    ]
  }
}

骑行路线规划

http
GET https://api.map.baidu.com/direction/v2/riding?origin=40.056,116.308&destination=39.915,116.404&output=json&ak=您的密钥
参数说明
riding_type骑行类型:0普通,1电动

步行路线规划

http
GET https://api.map.baidu.com/direction/v2/walking?origin=40.056,116.308&destination=39.915,116.404&output=json&ak=您的密钥

公交路线规划

http
GET https://api.map.baidu.com/direction/v2/transit?origin=40.056,116.308&destination=39.915,116.404&city=北京&output=json&ak=您的密钥
参数必填说明
origin起点(纬度,经度)
destination终点(纬度,经度)
city城市
tactics换乘策略

换乘策略:

说明
0推荐
1少换乘
2少步行
3不乘地铁
4时间短
5地铁优先

距离测量

http
GET https://api.map.baidu.com/routematrix/v2/driving?origins=40.056,116.308&destinations=39.915,116.404&output=json&ak=您的密钥
参数必填说明
origins起点坐标,多个用|分隔
destinations终点坐标,多个用|分隔
type测量方式:driving/walking/riding
tactics导航策略

响应示例:

json
{
  "status": 0,
  "result": [
    {
      "distance": {
        "text": "12.5公里",
        "value": 12500
      },
      "duration": {
        "text": "20分钟",
        "value": 1200
      },
      "origin": {"lng": 116.308, "lat": 40.056},
      "destination": {"lng": 116.404, "lat": 39.915}
    }
  ]
}

静态图

生成静态地图图片,适合简单展示场景。

http
GET https://api.map.baidu.com/staticimage/v2?center=116.404,39.915&zoom=15&width=400&height=300&ak=您的密钥
参数必填说明
center中心点坐标(经度,纬度)
zoom缩放级别(3-18)
width图片宽度(默认400,最大1024)
height图片高度(默认300,最大1024)
markers标注点
paths折线
labels标签
scale比例尺
dpiType分辨率:ph/high

添加标注

code
markers=116.404,39.915|116.408,39.920
markerStyles=样式配置

标注样式:

code
markerStyles=larger,l,A,0xFF0000
参数说明
size大小:small/normal/large/larger
label标签内容
color颜色(十六进制)

添加折线

code
paths=116.404,39.915;116.408,39.920;116.410,39.925
pathStyles=样式配置

坐标转换

将其他坐标系转换为百度坐标。

http
GET https://api.map.baidu.com/geoconv/v1/?coords=114.21892734521,29.575429778924&from=1&to=5&ak=您的密钥
参数必填说明
coords需转换的坐标,多个用|分隔
from源坐标类型
to目标坐标类型

坐标类型对照:

编号说明
1GPS坐标(WGS84)
2火星坐标(GCJ02)
3百度坐标(BD09)
4MapBar坐标
5百度坐标(BD09)
6搜狗坐标
751地图坐标
8谷歌坐标(GCJ02)

响应示例:

json
{
  "status": 0,
  "result": [
    {
      "x": 114.230,
      "y": 29.583
    }
  ]
}

行政区域

http
GET https://api.map.baidu.com/api_custom/v1/boundaries?keyword=海淀区&output=json&ak=您的密钥
参数必填说明
keyword行政区名称
sub_admin是否返回下级行政区:0否,1是
level行政区级别

响应示例:

json
{
  "status": 0,
  "boundaries": [
    {
      "name": "海淀区",
      "code": "110108",
      "boundary": "坐标点串"
    }
  ]
}

SDK封装示例

Node.js SDK

javascript
// baidu-map-sdk.js
const crypto = require('crypto');
const axios = require('axios');

class BaiduMapSDK {
  constructor(ak, sk = null) {
    this.ak = ak;
    this.sk = sk;
    this.baseUrl = 'https://api.map.baidu.com';
  }

  // 生成SN签名
  generateSn(query) {
    if (!this.sk) return null;
    const str = query + this.sk;
    return crypto.createHash('md5').update(encodeURIComponent(str)).digest('hex');
  }

  // 通用请求方法
  async request(path, params) {
    const queryString = new URLSearchParams(params).toString();
    const sn = this.generateSn(queryString);
    const url = `${this.baseUrl}${path}?${queryString}${sn ? '&sn=' + sn : ''}`;

    const response = await axios.get(url);
    
    if (response.data.status !== 0) {
      throw new Error(`API错误: ${response.data.message || response.data.status}`);
    }

    return response.data;
  }

  // 地理编码
  async geocode(address, city = null) {
    const params = { address, ak: this.ak, output: 'json' };
    if (city) params.city = city;
    return this.request('/geocoding/v3/', params);
  }

  // 逆地理编码
  async reverseGeocode(lat, lng) {
    return this.request('/reverse_geocoding/v3/', {
      location: `${lat},${lng}`,
      ak: this.ak,
      output: 'json'
    });
  }

  // 地点搜索
  async searchPlace(query, region, options = {}) {
    return this.request('/place/v2/search', {
      query,
      region,
      ak: this.ak,
      output: 'json',
      ...options
    });
  }

  // 路线规划
  async drivingRoute(originLat, originLng, destLat, destLng, options = {}) {
    return this.request('/direction/v2/driving', {
      origin: `${originLat},${originLng}`,
      destination: `${destLat},${destLng}`,
      ak: this.ak,
      output: 'json',
      ...options
    });
  }

  // 坐标转换
  async convertCoords(coords, from = 1, to = 5) {
    const coordsStr = coords.map(c => `${c.lng},${c.lat}`).join('|');
    return this.request('/geoconv/v1/', {
      coords: coordsStr,
      from,
      to,
      ak: this.ak,
      output: 'json'
    });
  }
}

module.exports = BaiduMapSDK;

使用示例

javascript
const BaiduMapSDK = require('./baidu-map-sdk');

// 初始化SDK
const bmap = new BaiduMapSDK('您的AK', '您的SK');

// 地理编码
async function test() {
  try {
    // 地址转坐标
    const geoResult = await bmap.geocode('北京市海淀区上地十街10号');
    console.log('坐标:', geoResult.result.location);

    // 坐标转地址
    const reverseResult = await bmap.reverseGeocode(39.915, 116.404);
    console.log('地址:', reverseResult.result.formatted_address);

    // 地点搜索
    const searchResult = await bmap.searchPlace('餐厅', '北京', { page_size: 10 });
    console.log('搜索结果:', searchResult.results);

    // 路线规划
    const routeResult = await bmap.drivingRoute(39.915, 116.404, 40.056, 116.308);
    console.log('距离:', routeResult.result.routes[0].distance);
  } catch (error) {
    console.error('错误:', error.message);
  }
}

test();

Python SDK示例

python
import hashlib
import requests
from urllib.parse import quote

class BaiduMapSDK:
    def __init__(self, ak, sk=None):
        self.ak = ak
        self.sk = sk
        self.base_url = 'https://api.map.baidu.com'

    def _generate_sn(self, query):
        if not self.sk:
            return None
        temp = query + self.sk
        return hashlib.md5(quote(temp).encode('utf-8')).hexdigest()

    def _request(self, path, params):
        params['ak'] = self.ak
        params['output'] = 'json'
        query = '&'.join([f'{k}={v}' for k, v in params.items()])
        sn = self._generate_sn(query)
        url = f'{self.base_url}{path}?{query}'
        if sn:
            url += f'&sn={sn}'
        
        response = requests.get(url)
        data = response.json()
        
        if data['status'] != 0:
            raise Exception(f"API错误: {data.get('message', data['status'])}")
        
        return data

    def geocode(self, address, city=None):
        params = {'address': address}
        if city:
            params['city'] = city
        return self._request('/geocoding/v3/', params)

    def reverse_geocode(self, lat, lng):
        return self._request('/reverse_geocoding/v3/', {
            'location': f'{lat},{lng}'
        })

    def search_place(self, query, region, **options):
        params = {'query': query, 'region': region, **options}
        return self._request('/place/v2/search', params)

    def driving_route(self, origin_lat, origin_lng, dest_lat, dest_lng, **options):
        params = {
            'origin': f'{origin_lat},{origin_lng}',
            'destination': f'{dest_lat},{dest_lng}',
            **options
        }
        return self._request('/direction/v2/driving', params)

最佳实践

安全签名

为防止AK被盗用,建议使用SN签名:

javascript
const crypto = require('crypto');

function generateSn(ak, sk, query) {
  const str = query + sk;
  return crypto.createHash('md5').update(encodeURIComponent(str)).digest('hex');
}

// 使用示例
const ak = '您的AK';
const sk = '您的SK';
const query = '/geocoding/v3/?address=北京&ak=' + ak + '&output=json';
const sn = generateSn(ak, sk, query);

错误处理

javascript
async function searchPlace(query) {
  try {
    const response = await fetch(url);
    const data = await response.json();
    
    if (data.status !== 0) {
      throw new Error(`API错误: ${data.message || data.status}`);
    }
    
    return data.results;
  } catch (error) {
    console.error('请求失败:', error);
    throw error;
  }
}

配额管理

javascript
const cache = new Map();
const CACHE_TTL = 5 * 60 * 1000; // 5分钟缓存

async function searchWithCache(query) {
  const cacheKey = `search_${query}`;
  
  // 检查缓存
  if (cache.has(cacheKey)) {
    const cached = cache.get(cacheKey);
    if (Date.now() - cached.time < CACHE_TTL) {
      return cached.data;
    }
  }
  
  // 请求数据
  const result = await searchPlace(query);
  
  // 更新缓存
  cache.set(cacheKey, {
    data: result,
    time: Date.now()
  });
  
  return result;
}

// 定期清理过期缓存
setInterval(() => {
  const now = Date.now();
  for (const [key, value] of cache.entries()) {
    if (now - value.time > CACHE_TTL) {
      cache.delete(key);
    }
  }
}, 60 * 1000);

批量请求

javascript
// 批量地理编码
async function batchGeocode(addresses) {
  const results = [];
  const concurrency = 10; // 并发数
  
  for (let i = 0; i < addresses.length; i += concurrency) {
    const batch = addresses.slice(i, i + concurrency);
    const promises = batch.map(addr => geocode(addr));
    const batchResults = await Promise.all(promises);
    results.push(...batchResults);
    
    // 避免超过QPS限制
    await new Promise(resolve => setTimeout(resolve, 100));
  }
  
  return results;
}

下一步